From 3cc12617b591ae393075a8e78dd2286944d8e2e2 Mon Sep 17 00:00:00 2001 From: Robin Lindner Date: Thu, 23 Jun 2022 09:14:58 +0200 Subject: [PATCH] Revert "Sfh fix tests (#8)" (#9) This reverts commit 5776aad0f1b35b6fdce1bca9407bcda4ed73e17f. --- .config/dotnet-tools.json | 2 +- Directory.Build.props | 1 - THIRD-PARTY-NOTICES.TXT | 37 - docs/coding-guidelines/clr-code-guide.md | 2 +- docs/coding-guidelines/mono-code-guide.md | 253 -- docs/design/coreclr/botr/dac-notes.md | 2 +- .../LibraryImportGenerator/Compatibility.md | 9 - .../LibraryImportGenerator/Pipeline.md | 12 +- .../LibraryImportGenerator/SpanMarshallers.md | 2 - .../StructMarshalling.md | 4 +- .../UserTypeMarshallingV2.md | 768 ---- docs/design/security/unix-tmp.md | 45 - docs/design/specs/Ecma-335-Augments.md | 5 - docs/project/dogfooding.md | 15 +- eng/CodeAnalysis.src.globalconfig | 29 +- eng/CodeAnalysis.test.globalconfig | 3 - eng/Subsets.props | 4 +- eng/Version.Details.xml | 184 +- eng/Versions.props | 86 +- eng/build.sh | 6 +- eng/common/init-tools-native.ps1 | 11 +- eng/common/native/init-compiler.sh | 2 +- eng/common/tools.ps1 | 4 - eng/native/build-commons.sh | 6 +- eng/native/configurecompiler.cmake | 10 - eng/native/configureplatform.cmake | 9 - eng/native/configuretools.cmake | 2 +- eng/native/functions.cmake | 4 - eng/native/init-os-and-arch.sh | 3 - eng/native/tryrun.cmake | 6 +- .../templates/runtimes/run-test-job.yml | 9 +- .../templates/wasm-library-aot-tests.yml | 2 - .../common/templates/wasm-library-tests.yml | 2 - eng/pipelines/coreclr/libraries-pgo.yml | 2 +- eng/pipelines/coreclr/templates/build-job.yml | 2 - eng/pipelines/libraries/run-test-job.yml | 3 +- .../runtime-extra-platforms-other.yml | 33 +- eng/pipelines/runtime-staging.yml | 2 - eng/pipelines/runtime.yml | 6 +- eng/testing/tests.props | 12 + eng/testing/tests.targets | 12 - eng/testing/tests.wasm.targets | 8 - eng/testing/xunit/xunit.console.targets | 5 - global.json | 12 +- ....PortableThreadPool.NativeSinks.CoreCLR.cs | 4 - .../src/System/Environment.CoreCLR.cs | 19 +- .../src/System/Exception.CoreCLR.cs | 27 - .../Reflection/Emit/DynamicILGenerator.cs | 2 +- .../src/System/Reflection/Emit/ILGenerator.cs | 156 +- .../System/Reflection/Emit/MethodBuilder.cs | 4 +- .../Reflection/MethodInvoker.CoreCLR.cs | 17 +- .../src/System/Reflection/RuntimeAssembly.cs | 5 +- .../Runtime/CompilerServices/CastHelpers.cs | 7 +- .../src/System/ValueType.cs | 2 +- src/coreclr/binder/assemblybindercommon.cpp | 3 +- src/coreclr/binder/customassemblybinder.cpp | 3 +- src/coreclr/binder/defaultassemblybinder.cpp | 3 +- .../binder/inc/assemblybindercommon.hpp | 1 - src/coreclr/binder/inc/customassemblybinder.h | 1 - .../binder/inc/defaultassemblybinder.h | 1 - src/coreclr/classlibnative/bcltype/system.cpp | 37 + src/coreclr/classlibnative/bcltype/system.h | 1 + src/coreclr/debug/daccess/daccess.cpp | 2 +- src/coreclr/debug/daccess/dacdbiimpl.cpp | 8 +- .../debug/daccess/ppc64le/primitives.cpp | 8 - src/coreclr/debug/daccess/request.cpp | 11 +- src/coreclr/debug/ee/debugger.cpp | 2 +- src/coreclr/debug/ee/debugger.h | 2 +- src/coreclr/debug/ee/functioninfo.cpp | 3 - src/coreclr/debug/ee/ppc64le/dbghelpers.S | 8 - src/coreclr/debug/ee/ppc64le/primitives.cpp | 9 - .../debug/shared/ppc64le/primitives.cpp | 15 - src/coreclr/dlls/mscorrc/mscorrc.rc | 1 + src/coreclr/dlls/mscorrc/resource.h | 1 + src/coreclr/gc/env/etmdummy.h | 1 - src/coreclr/gc/env/gcenv.os.h | 11 + src/coreclr/gc/gc.cpp | 22 +- src/coreclr/gc/unix/cgroup.cpp | 99 +- src/coreclr/gc/unix/gcenv.unix.cpp | 97 +- src/coreclr/gc/windows/gcenv.windows.cpp | 48 +- src/coreclr/ilasm/assembler.h | 4 + src/coreclr/ilasm/main.cpp | 4 + src/coreclr/ildasm/dasm.cpp | 1 + src/coreclr/ildasm/windasm.cpp | 91 +- src/coreclr/inc/contxt.h | 3471 +++++++++++++++++ src/coreclr/inc/corhlprpriv.h | 4 +- src/coreclr/inc/corinfo.h | 21 +- src/coreclr/inc/corjit.h | 21 +- src/coreclr/inc/crosscomp.h | 2 - src/coreclr/inc/defaultallocator.h | 48 + src/coreclr/inc/iallocator.h | 44 + src/coreclr/inc/icorjitinfoimpl_generated.h | 4 - src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/inc/jithelpers.h | 7 +- src/coreclr/inc/llvm/ELF.h | 4 +- src/coreclr/inc/pedecoder.h | 2 - src/coreclr/inc/readytorun.h | 2 +- src/coreclr/inc/regex_base.h | 972 +++++ src/coreclr/inc/regex_util.h | 208 + src/coreclr/inc/sstring.h | 66 +- src/coreclr/inc/sstring.inl | 125 +- src/coreclr/inc/static_assert.h | 6 + src/coreclr/inc/switches.h | 2 +- src/coreclr/inc/utilcode.h | 34 + src/coreclr/inc/volatile.h | 4 +- src/coreclr/jit/CMakeLists.txt | 18 +- src/coreclr/jit/ClrJit.PAL.exports | 1 - src/coreclr/jit/ClrJit.exports | 1 - src/coreclr/jit/ICorJitInfo_API_names.h | 1 - src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 9 - src/coreclr/jit/assertionprop.cpp | 92 +- src/coreclr/jit/block.h | 52 +- src/coreclr/jit/codegen.h | 9 +- src/coreclr/jit/codegenarm64.cpp | 165 +- src/coreclr/jit/codegenarmarch.cpp | 259 +- src/coreclr/jit/codegencommon.cpp | 30 +- src/coreclr/jit/codegenlinear.cpp | 68 +- src/coreclr/jit/codegenloongarch64.cpp | 12 - src/coreclr/jit/codegenxarch.cpp | 226 +- src/coreclr/jit/compiler.cpp | 44 +- src/coreclr/jit/compiler.h | 169 +- src/coreclr/jit/compiler.hpp | 26 +- src/coreclr/jit/decomposelongs.cpp | 3 + src/coreclr/jit/ee_il_dll.cpp | 62 +- src/coreclr/jit/emit.cpp | 194 +- src/coreclr/jit/emit.h | 8 +- src/coreclr/jit/emitarm.cpp | 104 +- src/coreclr/jit/emitarm.h | 8 - src/coreclr/jit/emitarm64.cpp | 454 +-- src/coreclr/jit/emitarm64.h | 18 +- src/coreclr/jit/emitloongarch64.cpp | 2 +- src/coreclr/jit/emitloongarch64.h | 6 - src/coreclr/jit/emitxarch.cpp | 29 +- src/coreclr/jit/emitxarch.h | 5 +- src/coreclr/jit/fgbasic.cpp | 2 +- src/coreclr/jit/fginline.cpp | 3 +- src/coreclr/jit/fgopt.cpp | 7 +- src/coreclr/jit/fgprofile.cpp | 321 +- src/coreclr/jit/flowgraph.cpp | 44 +- src/coreclr/jit/forwardsub.cpp | 40 +- src/coreclr/jit/gentree.cpp | 433 +- src/coreclr/jit/gentree.h | 175 +- src/coreclr/jit/gtlist.h | 1 - src/coreclr/jit/hwintrinsic.cpp | 70 +- src/coreclr/jit/importer.cpp | 745 ++-- src/coreclr/jit/indirectcalltransformer.cpp | 302 +- src/coreclr/jit/inline.cpp | 35 +- src/coreclr/jit/inline.h | 52 +- src/coreclr/jit/instrsxarch.h | 4 +- src/coreclr/jit/jit.h | 23 +- src/coreclr/jit/jitconfigvalues.h | 10 +- src/coreclr/jit/lclmorph.cpp | 72 +- src/coreclr/jit/lclvars.cpp | 161 +- src/coreclr/jit/likelyclass.cpp | 257 +- src/coreclr/jit/loopcloning.cpp | 19 - src/coreclr/jit/lower.cpp | 213 +- src/coreclr/jit/lower.h | 3 +- src/coreclr/jit/lowerarmarch.cpp | 145 +- src/coreclr/jit/lowerloongarch64.cpp | 24 - src/coreclr/jit/lowerxarch.cpp | 202 +- src/coreclr/jit/lsraarmarch.cpp | 51 +- src/coreclr/jit/lsraxarch.cpp | 24 +- src/coreclr/jit/morph.cpp | 1398 ++++--- src/coreclr/jit/optcse.cpp | 33 +- src/coreclr/jit/optimizer.cpp | 678 +--- src/coreclr/jit/patchpoint.cpp | 2 +- src/coreclr/jit/rangecheck.cpp | 81 +- src/coreclr/jit/rangecheck.h | 127 +- src/coreclr/jit/rationalize.cpp | 99 +- src/coreclr/jit/rationalize.h | 4 - src/coreclr/jit/scopeinfo.cpp | 4 +- src/coreclr/jit/simd.cpp | 61 +- src/coreclr/jit/targetamd64.h | 2 - src/coreclr/jit/targetarm.h | 1 - src/coreclr/jit/targetarm64.h | 1 - src/coreclr/jit/targetloongarch64.h | 1 - src/coreclr/jit/targetx86.h | 1 - src/coreclr/jit/unwind.cpp | 18 +- src/coreclr/jit/unwindamd64.cpp | 67 +- src/coreclr/jit/unwindarm.cpp | 45 +- src/coreclr/jit/unwindx86.cpp | 63 +- src/coreclr/jit/valuenum.cpp | 302 +- src/coreclr/jit/valuenum.h | 7 +- src/coreclr/minipal/Unix/doublemapping.cpp | 21 - .../BuildIntegration/BuildIntegration.proj | 5 - .../Microsoft.NETCore.Native.Unix.props | 1 + .../Microsoft.NETCore.Native.Windows.props | 6 - .../Microsoft.NETCore.Native.targets | 11 +- .../src/Internal/Runtime/MethodTable.cs | 8 +- .../DeveloperExperienceModeOnlyAttribute.cs | 46 + .../DeveloperExperienceState.cs | 1 + src/coreclr/nativeaot/Directory.Build.props | 2 +- .../src/System/Runtime/RuntimeExports.cs | 2 +- .../src/System/Runtime/ThunkPool.cs | 2 +- src/coreclr/nativeaot/Runtime/CMakeLists.txt | 5 +- src/coreclr/nativeaot/Runtime/startup.cpp | 57 - .../nativeaot/Runtime/unix/PalRedhawkUnix.cpp | 9 +- .../Runtime/windows/CoffNativeCodeManager.cpp | 61 +- .../src/ILLink/ILLink.Substitutions.xml | 3 - .../DeveloperExperience.cs | 2 +- .../Runtime/Augments/TypeLoaderCallbacks.cs | 5 - .../Runtime/CompilerHelpers/InteropHelpers.cs | 2 +- .../src/System.Private.CoreLib.csproj | 149 +- .../src/System/Array.NativeAot.cs | 2 +- .../src/System/Environment.NativeAot.cs | 7 - .../src/System/Helpers.cs | 27 + .../src/System/MulticastDelegate.cs | 4 +- .../src/System/Reflection/Emit/ILGenerator.cs | 2 +- .../ClassConstructorRunner.cs | 2 +- .../NativeLibrary.NativeAot.Unix.cs | 9 +- .../src/System/Runtime/RuntimeImports.cs | 26 +- .../src/System/RuntimeTypeHandle.cs | 3 +- .../Win32ThreadPoolPreAllocatedOverlapped.cs | 2 +- .../src/System/Type.Internal.cs | 30 +- .../Internal/Reflection/RuntimeTypeInfo.cs | 30 - .../src/ILLink/ILLink.Substitutions.xml | 5 + .../Core/Execution/ExecutionDomain.cs | 17 +- .../Core/Execution/ExecutionEnvironment.cs | 3 - .../Core/Execution/FieldAccessor.cs | 3 - .../Core/Execution/MethodInvoker.cs | 8 +- .../Core/Execution/ReflectionCoreExecution.cs | 3 - .../Reflection/Core/ReflectionDomainSetup.cs | 7 +- .../src/Resources/Strings.resx | 369 ++ .../src/System.Private.Reflection.Core.csproj | 200 + .../src/System/ActivatorImplementation.cs | 10 +- ...imeAssembly.GetTypeCore.CaseInsensitive.cs | 2 +- ...ntimeAssembly.GetTypeCore.CaseSensitive.cs | 0 .../NativeFormatRuntimeAssembly.cs | 4 +- .../Runtime/Assemblies/RuntimeAssemblyInfo.cs | 12 +- .../BindingFlagSupport/ConstructorPolicies.cs | 4 +- .../BindingFlagSupport/EventPolicies.cs | 28 +- .../BindingFlagSupport/FieldPolicies.cs | 2 +- .../BindingFlagSupport/MemberPolicies.cs | 2 +- .../BindingFlagSupport/MemberTypeIndex.cs | 0 .../BindingFlagSupport/MethodPolicies.cs | 6 +- .../NameFilter.NativeFormat.cs | 0 .../Runtime/BindingFlagSupport/NameFilter.cs | 0 .../BindingFlagSupport/NestedTypePolicies.cs | 2 +- .../BindingFlagSupport/PropertyPolicies.cs | 18 +- .../BindingFlagSupport/QueriedMemberList.cs | 2 +- .../QueryResult.Enumerator.cs | 0 .../Runtime/BindingFlagSupport/QueryResult.cs | 4 +- .../Runtime/BindingFlagSupport/Shared.cs | 4 +- .../NativeFormatCustomAttributeData.cs | 18 +- .../RuntimeCustomAttributeData.cs | 10 +- .../RuntimePseudoCustomAttributeData.cs | 0 .../Dispensers/DefaultDispenserPolicy.cs | 0 .../Runtime/Dispensers/Dispenser.cs | 0 .../Runtime/Dispensers/DispenserAlgorithm.cs | 0 .../Runtime/Dispensers/DispenserFactory.cs | 0 .../Runtime/Dispensers/DispenserPolicy.cs | 0 .../Runtime/Dispensers/DispenserScenario.cs | 0 .../Dispensers/DispenserThatAlwaysCreates.cs | 0 .../Dispensers/DispenserThatAlwaysReuses.cs | 0 .../DispenserThatReusesAsLongAsKeyIsAlive.cs | 0 ...nserThatReusesAsLongAsKeyedValueIsAlive.cs | 0 ...DispenserThatReusesAsLongAsValueIsAlive.cs | 0 .../NativeFormatRuntimeEventInfo.cs | 0 .../Runtime/EventInfos/RuntimeEventInfo.cs | 0 .../NativeFormatRuntimeFieldInfo.cs | 6 +- .../Runtime/FieldInfos/RuntimeFieldInfo.cs | 0 .../Runtime/General/Assignability.cs | 18 +- .../BlockedRuntimeTypeNameGenerator.cs | 0 .../General/Dispensers.NativeFormat.cs | 2 +- .../Reflection/Runtime/General/Dispensers.cs | 6 +- .../Runtime/General/Helpers.NativeFormat.cs | 0 .../Reflection/Runtime/General/Helpers.cs | 12 +- ...ntimeMemberInfoWithNoMetadataDefinition.cs | 0 .../General/LegacyCustomAttributeApis.cs | 0 .../Reflection/Runtime/General/ListBuilder.cs | 0 .../MetadataReaderExtensions.NativeFormat.cs | 33 +- .../Runtime/General/NamespaceChain.cs | 2 +- .../NativeFormat/DefaultValueParser.cs | 2 +- .../Runtime/General/NonOverriddenApis.cs | 217 ++ .../QSignatureTypeHandle.NativeFormat.cs | 0 .../Runtime/General/QSignatureTypeHandle.cs | 15 +- .../ReflectionCoreCallbacksImplementation.cs | 4 +- .../Runtime/General/RuntimeTypeHandleKey.cs | 0 .../Reflection/Runtime/General/ThunkedApis.cs | 9 +- .../Runtime/General/ToStringUtils.cs | 2 +- .../Reflection/Runtime/General/TypeContext.cs | 0 .../Runtime/General/TypeForwardInfo.cs | 0 .../General/TypeResolver.NativeFormat.cs | 30 +- .../Runtime/General/TypeResolver.cs | 6 +- .../General/TypeUnifier.NativeFormat.cs | 0 .../Reflection/Runtime/General/TypeUnifier.cs | 2 +- .../MethodInfos/CustomMethodInvoker.cs | 2 +- .../MethodInfos/CustomMethodInvokerAction.cs | 0 .../CustomMethodMapper.Nullable.cs | 3 +- .../MethodInfos/CustomMethodMapper.String.cs | 0 .../Runtime/MethodInfos/CustomMethodMapper.cs | 6 +- .../MethodInfos/IRuntimeMethodCommon.cs | 0 .../Runtime/MethodInfos/InvokerOptions.cs | 0 .../NativeFormat/NativeFormatMethodCommon.cs | 8 +- .../Runtime/MethodInfos/OpenMethodInvoker.cs | 2 +- .../RuntimeClsIdNullaryConstructorInfo.cs | 4 +- .../RuntimeConstructedGenericMethodInfo.cs | 2 +- .../MethodInfos/RuntimeConstructorInfo.cs | 8 +- .../MethodInfos/RuntimeDummyMethodInfo.cs | 2 +- .../MethodInfos/RuntimeMethodHelpers.cs | 2 +- .../Runtime/MethodInfos/RuntimeMethodInfo.cs | 6 +- .../MethodInfos/RuntimeNamedMethodInfo.cs | 6 +- .../RuntimePlainConstructorInfo.cs | 6 +- .../RuntimeSyntheticConstructorInfo.cs | 6 +- .../MethodInfos/RuntimeSyntheticMethodInfo.cs | 4 +- .../Runtime/MethodInfos/SyntheticMethodId.cs | 0 .../VirtualRuntimeParameterInfoArray.cs | 0 .../NativeFormat/NativeFormatRuntimeModule.cs | 0 .../Runtime/Modules/RuntimeModule.cs | 2 + .../NativeFormatMethodParameterInfo.cs | 2 +- .../RuntimeFatMethodParameterInfo.cs | 0 .../RuntimeMethodParameterInfo.cs | 0 .../ParameterInfos/RuntimeParameterInfo.cs | 0 .../RuntimePropertyIndexParameterInfo.cs | 0 .../RuntimeSyntheticParameterInfo.cs | 2 +- .../RuntimeThinMethodParameterInfo.cs | 2 +- .../EcmaFormatRuntimePropertyInfo.cs | 0 .../NativeFormatRuntimePropertyInfo.cs | 2 +- .../PropertyInfos/RuntimePropertyInfo.cs | 8 +- ...veFormatRuntimeGenericParameterTypeInfo.cs | 2 +- ...ameterTypeInfoForMethods.UnificationKey.cs | 0 ...ntimeGenericParameterTypeInfoForMethods.cs | 0 ...arameterTypeInfoForTypes.UnificationKey.cs | 0 ...RuntimeGenericParameterTypeInfoForTypes.cs | 0 ...rmatRuntimeNamedTypeInfo.UnificationKey.cs | 0 .../NativeFormatRuntimeNamedTypeInfo.cs | 10 +- ...veFormatRuntimeTypeInfo.CoreGetDeclared.cs | 0 .../Runtime/TypeInfos/RuntimeArrayTypeInfo.cs | 0 .../TypeInfos/RuntimeBlockedTypeInfo.cs | 4 +- .../Runtime/TypeInfos/RuntimeByRefTypeInfo.cs | 0 .../RuntimeClsIdTypeInfo.UnificationKey.cs | 0 .../Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs | 4 +- ...nstructedGenericTypeInfo.UnificationKey.cs | 0 .../RuntimeConstructedGenericTypeInfo.cs | 4 +- .../RuntimeGenericParameterTypeInfo.cs | 0 ...untimeHasElementTypeInfo.UnificationKey.cs | 0 .../TypeInfos/RuntimeHasElementTypeInfo.cs | 6 +- .../Runtime/TypeInfos/RuntimeNamedTypeInfo.cs | 10 +- .../RuntimeNoMetadataNamedTypeInfo.cs | 2 +- .../TypeInfos/RuntimePointerTypeInfo.cs | 0 .../RuntimeTypeDefinitionTypeInfo.cs | 0 .../TypeInfos/RuntimeTypeInfo.BindingFlags.cs | 0 .../RuntimeTypeInfo.CoreGetDeclared.cs | 10 +- .../TypeInfos/RuntimeTypeInfo.GetMember.cs | 19 +- .../TypeInfos/RuntimeTypeInfo.InvokeMember.cs | 49 +- .../RuntimeTypeInfo.TypeComponentsCache.cs | 0 .../Runtime/TypeInfos/RuntimeTypeInfo.cs | 30 +- .../Runtime/TypeParsing/GetTypeOptions.cs | 0 .../Runtime/TypeParsing/TypeLexer.cs | 0 .../Runtime/TypeParsing/TypeName.cs | 2 +- .../Runtime/TypeParsing/TypeParser.cs | 2 +- ...EnvironmentImplementation.MappingTables.cs | 30 +- ...PointerTypeFieldAccessorForStaticFields.cs | 4 +- ...ferenceTypeFieldAccessorForStaticFields.cs | 4 +- .../ValueTypeFieldAccessorForStaticFields.cs | 4 +- .../MissingMetadataExceptionCreator.cs | 23 +- ...System.Private.Reflection.Execution.csproj | 1 + .../Reflection/Core/AssemblyBinder.cs | 5 - .../Runtime/TypeLoader/EETypeCreator.cs | 2 +- .../Runtime/TypeLoader/GenericDictionary.cs | 2 +- .../TypeLoader/GenericDictionaryCell.cs | 18 +- .../TypeLoader}/MetadataReaderExtensions.cs | 11 +- .../Internal/Runtime/TypeLoader/ModuleList.cs | 10 +- .../TypeLoader/NativeLayoutFieldAlgorithm.cs | 4 +- .../TypeLoader/NativeLayoutFieldDesc.cs | 2 - .../NoMetadataFieldLayoutAlgorithm.cs | 4 +- .../Runtime/TypeLoader/TypeBuilder.cs | 22 +- .../Runtime/TypeLoader/TypeBuilderState.cs | 4 +- ...peLoaderEnvironment.LdTokenResultLookup.cs | 14 +- .../TypeLoaderEnvironment.Metadata.cs | 2 +- .../TypeLoaderEnvironment.NamedTypeLookup.cs | 8 +- .../TypeLoaderEnvironment.SignatureParsing.cs | 2 +- .../TypeLoader/TypeLoaderEnvironment.cs | 15 - .../Internal/TypeSystem/TypeDesc.Runtime.cs | 8 +- .../TypeSystem/TypeSystemContext.Runtime.cs | 4 +- .../src/System.Private.TypeLoader.csproj | 4 + .../Runtime/General/QHandles.NativeFormat.cs | 1 + .../Reflection/Runtime/General/QHandles.cs | 13 - .../src/System/Runtime/RuntimeImports.cs | 6 +- src/coreclr/nativeaot/docs/optimizing.md | 19 +- .../nativeaot/docs/reflection-free-mode.md | 2 +- src/coreclr/nativeaot/nativeaot.sln | 2 + src/coreclr/pal/inc/pal.h | 153 - src/coreclr/pal/inc/pal_endian.h | 2 +- src/coreclr/pal/inc/rt/intsafe.h | 1401 +++++++ src/coreclr/pal/inc/rt/palrt.h | 8 - src/coreclr/pal/inc/unixasmmacros.inc | 4 +- src/coreclr/pal/inc/unixasmmacrosppc64le.inc | 37 - src/coreclr/pal/src/CMakeLists.txt | 2 - .../pal/src/arch/ppc64le/asmconstants.h | 89 - .../arch/ppc64le/callsignalhandlerwrapper.S | 31 - src/coreclr/pal/src/arch/ppc64le/context2.S | 188 - src/coreclr/pal/src/arch/ppc64le/debugbreak.S | 10 - .../pal/src/arch/ppc64le/exceptionhelper.S | 63 - .../pal/src/arch/ppc64le/processor.cpp | 21 - .../src/arch/ppc64le/signalhandlerhelper.cpp | 68 - src/coreclr/pal/src/cruntime/file.cpp | 2 +- src/coreclr/pal/src/cruntime/printf.cpp | 22 +- src/coreclr/pal/src/cruntime/printfcpp.cpp | 18 +- .../pal/src/cruntime/silent_printf.cpp | 4 +- .../pal/src/exception/remote-unwind.cpp | 63 +- src/coreclr/pal/src/exception/seh-unwind.cpp | 60 - src/coreclr/pal/src/file/filetime.cpp | 12 +- src/coreclr/pal/src/include/pal/context.h | 89 - src/coreclr/pal/src/include/pal/virtual.h | 13 +- src/coreclr/pal/src/locale/utf8.cpp | 2 +- src/coreclr/pal/src/map/map.cpp | 8 +- src/coreclr/pal/src/map/virtual.cpp | 24 +- src/coreclr/pal/src/misc/cgroup.cpp | 99 +- src/coreclr/pal/src/misc/perfjitdump.cpp | 2 - src/coreclr/pal/src/misc/sysinfo.cpp | 91 +- src/coreclr/pal/src/misc/time.cpp | 16 +- src/coreclr/pal/src/safecrt/input.inl | 8 +- src/coreclr/pal/src/safecrt/wcslwr_s.cpp | 2 +- src/coreclr/pal/src/thread/context.cpp | 58 +- src/coreclr/scripts/superpmi.py | 14 - src/coreclr/scripts/superpmi_aspnet.py | 4 +- .../Common/Compiler/DisplayNameHelpers.cs | 2 +- .../Internal/Runtime/EETypeBuilderHelpers.cs | 2 +- .../Common/Internal/Runtime/ModuleHeaders.cs | 2 +- .../tools/Common/JitInterface/CorInfoBase.cs | 349 +- .../Common/JitInterface/CorInfoHelpFunc.cs | 7 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 114 +- .../tools/Common/JitInterface/CorInfoTypes.cs | 6 +- .../ThunkGenerator/ThunkInput.txt | 1 - src/coreclr/tools/Common/Pgo/PgoFormat.cs | 1 - .../Common/ExplicitLayoutValidator.cs | 2 +- .../Common/TypeSystem/Common/FieldDesc.cs | 3 - .../Common/FieldForInstantiatedType.cs | 5 - .../TypeSystem/Common/InstantiatedType.cs | 2 +- .../Common/TypeHashingAlgorithms.cs | 2 +- .../tools/Common/TypeSystem/Ecma/EcmaField.cs | 13 - .../TypeSystem/Ecma/EcmaSignatureParser.cs | 19 - .../tools/Common/TypeSystem/Ecma/EcmaType.cs | 7 +- .../IL/Stubs/PInvokeLazyFixupField.cs | 2 - .../TypeSystem/Interop/IL/InlineArrayType.cs | 1 - .../TypeSystem/Interop/IL/NativeStructType.cs | 2 - .../TypeSystemMetadataEmitter.cs | 228 +- src/coreclr/tools/aot/.editorconfig | 81 - .../Compiler/BodySubstitution.cs | 56 - .../Compiler/BodySubstitutionParser.cs | 172 - .../Compiler/Compilation.cs | 7 - .../Compiler/Dataflow/ReflectionMarker.cs | 4 +- .../Dataflow/ReflectionMethodBodyScanner.cs | 8 +- .../DependencyAnalysis/CanonicalEETypeNode.cs | 5 - .../ConstructedEETypeNode.cs | 5 - ...CustomAttributeBasedDependencyAlgorithm.cs | 26 +- .../Compiler/DependencyAnalysis/EETypeNode.cs | 19 +- .../DependencyAnalysis/FieldMetadataNode.cs | 2 +- .../DependencyAnalysis/GCStaticsNode.cs | 1 - .../GenericDictionaryNode.cs | 9 - .../DependencyAnalysis/MethodMetadataNode.cs | 2 +- .../DependencyAnalysis/NodeFactory.cs | 11 - .../DependencyAnalysis/NonGCStaticsNode.cs | 1 - .../ReadyToRunGenericHelperNode.cs | 2 - .../ReflectableFieldNode.cs | 105 - .../DependencyAnalysis/ThreadStaticsNode.cs | 3 +- .../DependencyAnalysis/TypeMetadataNode.cs | 19 +- .../Compiler/ExternSymbolMappedField.cs | 1 - .../Compiler/FeatureSwitchManager.cs | 165 +- .../Compiler/IRootingServiceProvider.cs | 1 - .../Compiler/LazyGenerics/GraphBuilder.cs | 7 +- .../Compiler/MetadataManager.cs | 44 +- .../Compiler/ProcessLinkerXmlBase.cs | 29 +- .../Compiler/RootingHelpers.cs | 95 +- .../Compiler/RootingServiceProvider.cs | 6 - .../Compiler/UsageBasedMetadataManager.cs | 289 +- .../IL/ILImporter.Scanner.cs | 5 +- .../ILCompiler.Compiler.csproj | 3 - .../aot/ILCompiler.Diagnostics/PdbWriter.cs | 7 +- .../SymNgenWriterWrapper.cs | 1 - .../ReadyToRunCodegenNodeFactory.cs | 2 +- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 65 +- .../JitInterface/CorInfoImpl.RyuJit.cs | 19 +- .../ILTestAssembly/Signature.il | 2 - .../SignatureTests.cs | 29 - src/coreclr/tools/aot/ILCompiler/Program.cs | 19 +- .../AddedPseudoAttributeAttribute.cs | 15 - .../BaseExpectedLinkedBehaviorAttribute.cs | 16 - .../Assertions/BaseInAssemblyAttribute.cs | 9 - .../BaseMemberAssertionAttribute.cs | 15 - .../Assertions/CreatedMemberAttribute.cs | 18 - .../Assertions/DependencyRecordedAttribute.cs | 20 - .../Assertions/DisplayNameAttribute.cs | 12 - .../Assertions/EnableLoggerAttribute.cs | 9 - .../Assertions/ExpectBodyModifiedAttribute.cs | 12 - ...ResolvedDocumentationSignatureAttribute.cs | 14 - ...xpectExceptionHandlersModifiedAttribute.cs | 12 - ...eneratedDocumentationSignatureAttribute.cs | 14 - .../ExpectLocalsModifiedAttribute.cs | 12 - ...ResolvedDocumentationSignatureAttribute.cs | 14 - ...resolvedDocumentationSignatureAttribute.cs | 14 - .../ExpectedInstructionSequenceAttribute.cs | 17 - ...tionSequenceOnMemberInAssemblyAttribute.cs | 35 - .../ExpectedLocalsSequenceAttribute.cs | 23 - .../Assertions/ExpectedNoWarningsAttribute.cs | 17 - .../Assertions/ExpectedWarningAttribute.cs | 30 - .../Assertions/IgnoreTestCaseAttribute.cs | 18 - ...ptAllTypesAndMembersInAssemblyAttribute.cs | 17 - .../Assertions/KeptAssemblyAttribute.cs | 21 - .../Assertions/KeptAttribute.cs | 12 - .../Assertions/KeptAttributeAttribute.cs | 24 - .../KeptAttributeInAssemblyAttribute.cs | 71 - ...KeptAttributeOnFixedBufferTypeAttribute.cs | 23 - .../Assertions/KeptBackingFieldAttribute.cs | 12 - .../KeptBaseOnTypeInAssemblyAttribute.cs | 37 - .../Assertions/KeptBaseTypeAttribute.cs | 25 - .../KeptDelegateCacheFieldAttribute.cs | 17 - .../Assertions/KeptEventAddMethodAttribute.cs | 12 - .../KeptEventRemoveMethodAttribute.cs | 12 - .../Assertions/KeptExportedTypeAttribute.cs | 20 - .../Assertions/KeptFixedBufferAttribute.cs | 12 - .../Assertions/KeptInitializerData.cs | 22 - .../Assertions/KeptInterfaceAttribute.cs | 26 - .../KeptInterfaceOnTypeInAssemblyAttribute.cs | 37 - .../Assertions/KeptMemberAttribute.cs | 18 - .../KeptMemberInAssemblyAttribute.cs | 34 - .../KeptModuleReferenceAttribute.cs | 20 - .../Assertions/KeptReferenceAttribute.cs | 20 - .../KeptReferencesInAssemblyAttribute.cs | 20 - .../Assertions/KeptResourceAttribute.cs | 20 - .../KeptResourceInAssemblyAttribute.cs | 23 - .../Assertions/KeptSecurityAttribute.cs | 23 - .../Assertions/KeptSymbolsAttribute.cs | 17 - .../Assertions/KeptTypeInAssemblyAttribute.cs | 27 - .../Assertions/LogContainsAttribute.cs | 26 - .../Assertions/LogDoesNotContainAttribute.cs | 26 - .../Assertions/NoLinkedOutputAttribute.cs | 13 - .../Assertions/ProducedBy.cs | 21 - .../Assertions/RemovedAssemblyAttribute.cs | 21 - .../Assertions/RemovedAssemblyReference.cs | 18 - .../Assertions/RemovedAttributeInAssembly.cs | 71 - .../Assertions/RemovedForwarderAttribute.cs | 18 - ...movedInterfaceOnTypeInAssemblyAttribute.cs | 37 - .../RemovedMemberInAssemblyAttribute.cs | 32 - .../Assertions/RemovedNameValueAttribute.cs | 15 - .../RemovedPseudoAttributeAttribute.cs | 15 - .../RemovedResourceInAssemblyAttribute.cs | 23 - .../Assertions/RemovedSymbolsAttribute.cs | 17 - .../RemovedTypeInAssemblyAttribute.cs | 27 - .../SkipKeptItemsValidationAttribute.cs | 13 - .../Assertions/SkipPeVerifyAttribute.cs | 29 - .../SkipRemainingErrorsValidationAttribute.cs | 13 - .../TestCaseRequirementsAttribute.cs | 17 - .../Assertions/TestRunCharacteristics.cs | 17 - .../VerifyMetadataNamesAttribute.cs | 15 - .../Helpers/DataFlowStringExtensions.cs | 42 - .../Helpers/DataFlowTypeExtensions.cs | 43 - .../Helpers/PlatformAssemblies.cs | 14 - .../Metadata/BaseMetadataAttribute.cs | 13 - .../Metadata/DefineAttribute.cs | 17 - .../Metadata/IgnoreDescriptorsAttribute.cs | 15 - .../Metadata/IgnoreLinkAttributesAttribute.cs | 15 - .../Metadata/IgnoreSubstitutionsAttribute.cs | 15 - .../Metadata/Il8nAttribute.cs | 18 - ...eepTypeForwarderOnlyAssembliesAttribute.cs | 17 - .../Metadata/NotATestCaseAttribute.cs | 12 - .../Metadata/ReferenceAttribute.cs | 18 - .../Metadata/ReferenceDependencyAttribute.cs | 17 - .../Metadata/SandboxDependencyAttribute.cs | 24 - .../SetupCSharpCompilerToUseAttribute.cs | 17 - .../Metadata/SetupCompileAfterAttribute.cs | 36 - .../Metadata/SetupCompileArgumentAttribute.cs | 17 - .../SetupCompileAsLibraryAttribute.cs | 12 - .../SetupCompileAssemblyNameAttribute.cs | 17 - .../Metadata/SetupCompileBeforeAttribute.cs | 58 - .../Metadata/SetupCompileResourceAttribute.cs | 17 - .../Metadata/SetupLinkAttributesFile.cs | 15 - .../Metadata/SetupLinkerActionAttribute.cs | 17 - .../Metadata/SetupLinkerArgumentAttribute.cs | 24 - .../SetupLinkerDefaultActionAttribute.cs | 17 - .../Metadata/SetupLinkerDescriptorFile.cs | 15 - .../SetupLinkerKeepDebugMembersAttribute.cs | 17 - ...SetupLinkerLinkPublicAndFamilyAttribute.cs | 12 - .../SetupLinkerLinkSymbolsAttribute.cs | 17 - .../SetupLinkerResponseFileAttribute.cs | 17 - .../SetupLinkerSubstitutionFileAttribute.cs | 17 - .../Metadata/SetupLinkerTrimModeAttribute.cs | 17 - .../Metadata/SkipUnresolvedAttribute.cs | 15 - .../Metadata/StripDescriptorsAttribute.cs | 15 - .../Metadata/StripLinkAttributesAttribute.cs | 15 - .../Metadata/StripSubstitutionsAttribute.cs | 15 - ...ono.Linker.Tests.Cases.Expectations.csproj | 10 - .../Support/IntrinsicAttribute.cs | 12 - .../RemoveAttributeInstancesAttribute.cs | 17 - .../DataFlow/AssemblyQualifiedNameDataflow.cs | 163 - .../DataFlow/EmptyArrayIntrinsicsDataFlow.cs | 60 - .../DataFlow/GetInterfaceDataFlow.cs | 198 - .../GetNestedTypeOnAllAnnotatedType.cs | 141 - .../DataFlow/GetTypeDataFlow.cs | 220 -- .../DataFlow/GetTypeInfoDataFlow.cs | 54 - .../DataFlow/MemberTypesRelationships.cs | 275 -- .../DataFlow/TypeInfoAsTypeDataFlow.cs | 55 - .../DataFlow/UnsafeDataFlow.cs | 68 - .../Mono.Linker.Tests.Cases.csproj | 17 - .../Mono.Linker.Tests.Cases/Repro/Program.cs | 30 - .../RequiresCapability/BasicRequires.cs | 215 - .../Extensions/CecilExtensions.cs | 368 -- .../Mono.Linker.Tests/Extensions/NiceIO.cs | 864 ---- .../Mono.Linker.Tests.csproj | 51 - .../Mono.Linker.Tests/TestCases/TestCase.cs | 59 - .../TestCases/TestDatabase.cs | 76 - .../Mono.Linker.Tests/TestCases/TestSuites.cs | 45 - .../TestCasesRunner/AssemblyChecker.cs | 960 ----- .../TestCasesRunner/BaseMetadataProvider.cs | 96 - .../TestCasesRunner/CompilerOptions.cs | 20 - .../TestCasesRunner/ExpectationsProvider.cs | 26 - .../TestCasesRunner/FormattingUtils.cs | 64 - .../TestCasesRunner/ILCompilerDriver.cs | 137 - .../TestCasesRunner/ILCompilerOptions.cs | 16 - .../ILCompilerOptionsBuilder.cs | 253 -- .../ILCompilerTestCaseResult.cs | 31 - .../TestCasesRunner/ILInputCompiler.cs | 93 - .../TestCasesRunner/IgnoreTestException.cs | 12 - .../ManagedCompilationResult.cs | 20 - .../TestCasesRunner/ObjectFactory.cs | 41 - .../TestCasesRunner/PathUtilities.cs | 35 - .../TestCasesRunner/ResultChecker.cs | 405 -- .../TestCasesRunner/SetupCompileInfo.cs | 23 - .../SourceAndDestinationPair.cs | 15 - .../TestCaseAssemblyResolver.cs | 43 - .../TestCasesRunner/TestCaseCollector.cs | 165 - .../TestCaseCompilationMetadataProvider.cs | 242 -- .../TestCasesRunner/TestCaseCompiler.cs | 411 -- .../TestCasesRunner/TestCaseLinkerOptions.cs | 36 - .../TestCaseMetadataProvider.cs | 141 - .../TestCasesRunner/TestCaseSandbox.cs | 195 - .../TestCasesRunner/TestLogWriter.cs | 57 - .../TestCasesRunner/TestRunner.cs | 165 - src/coreclr/tools/aot/ilc.sln | 68 +- .../tools/aot/jitinterface/jitinterface.h | 10 - src/coreclr/tools/dotnet-pgo/MibcEmitter.cs | 2 - .../TypeRefTypeSystemContext.cs | 4 +- .../TypeRefTypeSystemField.cs | 6 +- .../TypeRefTypeSystemType.cs | 4 +- .../tools/superpmi/mcs/verbdumpmap.cpp | 8 +- .../tools/superpmi/mcs/verbjitflags.cpp | 8 +- .../superpmi-shared/methodcontext.cpp | 11 +- .../superpmi/superpmi-shared/methodcontext.h | 5 +- .../superpmi-shared/spmidumphelper.cpp | 1 - .../superpmi-shim-collector/icorjitinfo.cpp | 7 - .../superpmi-shim-counter/icorjitinfo.cpp | 8 - .../superpmi-shim-simple/icorjitinfo.cpp | 7 - .../tools/superpmi/superpmi/icorjitinfo.cpp | 5 - .../tools/superpmi/superpmi/superpmi.cpp | 15 +- .../unwinder/ppc64le/unwinder_ppc64le.cpp | 11 - src/coreclr/utilcode/CMakeLists.txt | 1 + src/coreclr/utilcode/clrconfig.cpp | 14 +- src/coreclr/utilcode/debug.cpp | 8 +- src/coreclr/utilcode/executableallocator.cpp | 3 +- src/coreclr/utilcode/iallocator.cpp | 9 + src/coreclr/utilcode/prettyprintsig.cpp | 8 +- src/coreclr/utilcode/sstring.cpp | 116 +- src/coreclr/utilcode/util.cpp | 162 +- src/coreclr/vm/CMakeLists.txt | 2 + src/coreclr/vm/ClrEtwAll.man | 35 +- src/coreclr/vm/amd64/Context.asm | 16 +- .../vm/amd64/JitHelpers_InlineGetThread.asm | 13 +- src/coreclr/vm/amd64/JitHelpers_Slow.asm | 12 +- .../vm/amd64/RedirectedHandledJITCase.asm | 22 + src/coreclr/vm/amd64/asmconstants.h | 12 + src/coreclr/vm/amd64/cgencpu.h | 41 - src/coreclr/vm/amd64/excepamd64.cpp | 9 +- src/coreclr/vm/amd64/excepcpu.h | 2 +- src/coreclr/vm/amd64/virtualcallstubcpu.hpp | 37 +- src/coreclr/vm/appdomain.cpp | 8 +- src/coreclr/vm/appdomain.hpp | 6 +- src/coreclr/vm/arm/asmconstants.h | 9 + src/coreclr/vm/arm/cgencpu.h | 2 +- src/coreclr/vm/arm/ehhelpers.asm | 23 + src/coreclr/vm/arm/exceparm.cpp | 4 +- src/coreclr/vm/arm/excepcpu.h | 2 +- src/coreclr/vm/arm64/asmhelpers.asm | 23 + src/coreclr/vm/arm64/excepcpu.h | 2 +- src/coreclr/vm/array.cpp | 11 +- src/coreclr/vm/assembly.cpp | 9 +- src/coreclr/vm/assemblybinder.h | 2 +- src/coreclr/vm/assemblynative.cpp | 25 +- src/coreclr/vm/assemblynative.hpp | 2 +- src/coreclr/vm/assemblyspec.cpp | 20 +- src/coreclr/vm/bundle.cpp | 5 +- src/coreclr/vm/ceeload.cpp | 28 +- src/coreclr/vm/ceeload.h | 4 +- src/coreclr/vm/ceemain.cpp | 29 +- src/coreclr/vm/class.cpp | 14 +- src/coreclr/vm/class.h | 10 +- src/coreclr/vm/classhash.cpp | 6 +- src/coreclr/vm/classlayoutinfo.cpp | 10 +- src/coreclr/vm/clsload.cpp | 8 +- src/coreclr/vm/codeman.cpp | 33 +- src/coreclr/vm/codepitchingmanager.cpp | 12 +- src/coreclr/vm/codeversion.cpp | 2 +- src/coreclr/vm/comcache.cpp | 10 +- src/coreclr/vm/comcache.h | 6 +- src/coreclr/vm/comcallablewrapper.cpp | 27 +- src/coreclr/vm/comcallablewrapper.h | 10 +- src/coreclr/vm/comconnectionpoints.cpp | 8 +- src/coreclr/vm/comdelegate.cpp | 12 +- src/coreclr/vm/common.h | 12 + src/coreclr/vm/comsynchronizable.cpp | 5 +- src/coreclr/vm/comsynchronizable.h | 2 + src/coreclr/vm/comtoclrcall.cpp | 14 +- src/coreclr/vm/comutilnative.cpp | 169 +- src/coreclr/vm/coreassemblyspec.cpp | 8 +- src/coreclr/vm/corelib.h | 7 +- src/coreclr/vm/corhost.cpp | 60 +- src/coreclr/vm/crst.cpp | 4 +- src/coreclr/vm/crst.h | 4 +- src/coreclr/vm/ctxtcall.h | 409 ++ src/coreclr/vm/customattribute.cpp | 26 +- src/coreclr/vm/customattribute.h | 1 + src/coreclr/vm/dataimage.h | 19 + src/coreclr/vm/debugdebugger.cpp | 26 +- src/coreclr/vm/disassembler.cpp | 4 +- src/coreclr/vm/dllimport.cpp | 7 +- src/coreclr/vm/domainassembly.cpp | 4 +- src/coreclr/vm/dwbucketmanager.hpp | 12 +- src/coreclr/vm/dynamicmethod.cpp | 2 +- src/coreclr/vm/ecalllist.h | 3 + src/coreclr/vm/eeconfig.cpp | 65 +- src/coreclr/vm/eehash.inl | 4 +- src/coreclr/vm/eepolicy.cpp | 2 +- src/coreclr/vm/encee.cpp | 7 +- .../vm/eventing/eventpipe/ep-rt-coreclr.h | 3 +- src/coreclr/vm/eventreporter.cpp | 2 +- src/coreclr/vm/excep.cpp | 204 +- src/coreclr/vm/excep.h | 3 + src/coreclr/vm/exceptionhandling.cpp | 51 +- src/coreclr/vm/finalizerthread.cpp | 2 +- src/coreclr/vm/gccover.cpp | 38 +- src/coreclr/vm/gcenv.os.cpp | 47 +- src/coreclr/vm/gchelpers.cpp | 2 +- src/coreclr/vm/gdbjit.cpp | 15 +- src/coreclr/vm/genericdict.cpp | 4 +- src/coreclr/vm/generics.cpp | 8 +- src/coreclr/vm/genmeth.cpp | 3 +- src/coreclr/vm/hash.cpp | 6 +- src/coreclr/vm/hosting.cpp | 53 +- src/coreclr/vm/i386/excepx86.cpp | 6 +- src/coreclr/vm/i386/gmsx86.cpp | 1 - src/coreclr/vm/i386/jitinterfacex86.cpp | 24 +- src/coreclr/vm/i386/stublinkerx86.cpp | 2 +- src/coreclr/vm/ilmarshalers.cpp | 21 +- src/coreclr/vm/ilstubresolver.cpp | 6 +- src/coreclr/vm/instmethhash.h | 4 +- .../vm/interoplibinterface_comwrappers.cpp | 9 +- src/coreclr/vm/interoplibinterface_objc.cpp | 6 +- src/coreclr/vm/interoputil.cpp | 2 +- src/coreclr/vm/invokeutil.cpp | 20 +- src/coreclr/vm/jithelpers.cpp | 403 +- src/coreclr/vm/jitinterface.cpp | 39 +- src/coreclr/vm/jitinterface.h | 2 +- src/coreclr/vm/listlock.h | 4 +- src/coreclr/vm/loaderallocator.cpp | 19 +- src/coreclr/vm/loongarch64/excepcpu.h | 2 +- src/coreclr/vm/metasig.h | 5 +- src/coreclr/vm/method.cpp | 52 +- src/coreclr/vm/method.hpp | 2 +- src/coreclr/vm/methodtable.cpp | 44 +- src/coreclr/vm/methodtable.h | 19 +- src/coreclr/vm/methodtablebuilder.cpp | 9 +- src/coreclr/vm/mlinfo.cpp | 5 +- src/coreclr/vm/mngstdinterfaces.h | 2 +- src/coreclr/vm/multicorejit.cpp | 3 +- src/coreclr/vm/multicorejitplayer.cpp | 2 +- src/coreclr/vm/nativeeventsource.cpp | 10 - src/coreclr/vm/nativeeventsource.h | 1 - src/coreclr/vm/nativelibrary.cpp | 15 +- src/coreclr/vm/object.h | 30 +- src/coreclr/vm/olecontexthelpers.cpp | 8 +- src/coreclr/vm/olecontexthelpers.h | 4 +- src/coreclr/vm/olevariant.cpp | 166 +- src/coreclr/vm/peassembly.cpp | 6 +- src/coreclr/vm/peassembly.inl | 4 +- src/coreclr/vm/peimage.cpp | 8 +- src/coreclr/vm/peimage.inl | 2 +- src/coreclr/vm/peimagelayout.cpp | 10 +- src/coreclr/vm/peimagelayout.inl | 4 +- src/coreclr/vm/pgo.cpp | 21 +- src/coreclr/vm/ppc64le/unixstubs.cpp | 12 - src/coreclr/vm/profilinghelper.cpp | 6 +- src/coreclr/vm/proftoeeinterfaceimpl.cpp | 4 +- src/coreclr/vm/qcallentrypoints.cpp | 1 - src/coreclr/vm/sourceline.cpp | 328 ++ src/coreclr/vm/sourceline.h | 43 + src/coreclr/vm/spinlock.cpp | 4 +- src/coreclr/vm/spinlock.h | 4 +- src/coreclr/vm/stackcontents.h | 124 + src/coreclr/vm/stackwalk.cpp | 7 - src/coreclr/vm/stdinterfaces.cpp | 2 +- src/coreclr/vm/stdinterfaces_wrapper.cpp | 2 +- src/coreclr/vm/stubgen.cpp | 13 +- src/coreclr/vm/stubhelpers.cpp | 37 + src/coreclr/vm/stublink.cpp | 4 +- src/coreclr/vm/syncblk.cpp | 14 +- src/coreclr/vm/syncblk.h | 30 +- src/coreclr/vm/syncblk.inl | 17 - src/coreclr/vm/syncclean.cpp | 8 +- src/coreclr/vm/synch.cpp | 10 +- src/coreclr/vm/threadpoolrequest.cpp | 10 +- src/coreclr/vm/threadpoolrequest.h | 4 +- src/coreclr/vm/threads.cpp | 139 +- src/coreclr/vm/threads.h | 87 +- src/coreclr/vm/threadsuspend.cpp | 672 ++-- src/coreclr/vm/typedesc.cpp | 6 +- src/coreclr/vm/typedesc.h | 2 +- src/coreclr/vm/typehash.h | 4 +- src/coreclr/vm/typeparse.cpp | 5 +- src/coreclr/vm/util.cpp | 17 + src/coreclr/vm/util.hpp | 162 +- src/coreclr/vm/vars.hpp | 11 - src/coreclr/vm/virtualcallstub.cpp | 14 +- src/coreclr/vm/win32threadpool.cpp | 33 +- src/coreclr/vm/win32threadpool.h | 6 +- .../Bundle/Manifest.cs | 2 +- .../ComHost/ClsidMap.cs | 4 +- .../pkg/projects/netcoreappRIDs.props | 6 - .../MultiArchInstallLocation.cs | 82 - .../tests/HostActivation.Tests/SDKLookup.cs | 2 +- src/installer/tests/TestUtils/DotNetCli.cs | 30 +- .../tests/TestUtils/TestUtils.csproj | 2 +- .../Interop.X509Chain.cs | 4 + .../Interop.Sign.cs | 22 - .../Interop.SimpleDigestHash.cs | 4 +- .../Interop.Symmetric.cs | 8 + ...rop.ProcFsStat.TryReadProcessStatusInfo.cs | 1 - .../Unix/System.Native/Interop.Permissions.cs | 33 + .../Interop.NetSecurityNative.cs | 88 +- .../Interop.OpenSsl.cs | 2 +- .../Windows/Advapi32/Interop.LsaLookupSids.cs | 2 +- .../Windows/Crypt32/Interop.FindOidInfo.cs | 22 +- .../Windows/Crypt32/Interop.HashIdAlg.cs | 21 +- .../src/Interop/Windows/Interop.Errors.cs | 10 - .../Windows/IpHlpApi/Interop.FIXED_INFO.cs | 35 +- .../Interop/Windows/IpHlpApi/Interop.ICMP.cs | 31 +- .../IpHlpApi/Interop.IP_ADDR_STRING.cs | 12 +- .../IpHlpApi/Interop.NetworkInformation.cs | 89 +- ...Line.cs => Interop.VerSetConditionMask.cs} | 6 +- .../Kernel32/Interop.VerifyVersionExW.cs | 20 + .../Shell32/Interop.CommandLineToArgv.cs | 13 - .../GssSafeHandles.PlatformNotSupported.cs | 59 + .../Common/src/System/Console/ConsoleUtils.cs | 53 - .../Data/ProviderBase/DbMetaDataFactory.cs | 12 +- .../src/System/HashCodeRandomization.cs | 58 - .../src/System/IO/Archiving.Utils.Windows.cs | 35 +- .../Common/src/System/IO/Archiving.Utils.cs | 2 +- .../Common/src/System/IO/DelegatingStream.cs | 15 +- .../src/System/IO/ReadOnlyMemoryStream.cs | 14 +- .../Common/src/System/IO/RowConfigReader.cs | 2 +- ...extFlagsAdapterPal.PlatformNotSupported.cs | 22 + .../src/System/Net/Http/X509ResourceClient.cs | 9 +- .../aspnetcore/Http2/Hpack/IntegerDecoder.cs | 4 +- .../aspnetcore/Http2/Hpack/IntegerEncoder.cs | 4 +- .../Helpers/VariableLengthIntegerHelper.cs | 4 +- .../aspnetcore/Http3/QPack/QPackEncoder.cs | 10 +- .../src/System/Net/NTAuthentication.Common.cs | 57 +- .../System/Net/NTAuthentication.Managed.cs | 205 +- .../HostInformationPal.Windows.cs | 120 +- ...NegotiateStreamPal.PlatformNotSupported.cs | 124 + .../Net/Security/NegotiateStreamPal.Unix.cs | 29 +- .../Security/NegotiateStreamPal.Windows.cs | 211 +- .../System/Net/Security/SSPIHandleCache.cs | 11 +- .../Common/src/System/Net/SocketAddress.cs | 19 +- .../Common/src/System/Obsoletions.cs | 3 - .../Cryptography/Asn1Reader/AsnValueReader.cs | 7 - .../Security/Cryptography/Oids.Shared.cs | 2 - .../Common/src/System/Text/DBCSDecoder.cs | 6 +- .../Common/src/System/Text/OSEncoder.cs | 4 +- .../SingleFileTestRunner.cs | 15 +- .../System/IO/StreamConformanceTests.cs | 18 +- .../Common/tests/System/GenericMathHelpers.cs | 12 +- .../Net/Http/Http2LoopbackConnection.cs | 2 +- .../System/Net/Http/Http3LoopbackServer.cs | 18 +- .../HttpClientHandlerTest.Authentication.cs | 60 - ...ttpClientHandlerTest.ServerCertificates.cs | 10 +- .../Net/Security/FakeNegotiateServer.cs | 278 -- .../System/Reflection/InvokeEmitTests.cs | 56 - .../Reflection/InvokeInterpretedTests.cs | 53 - .../TestUtilities/System/PlatformDetection.cs | 1 - .../ComInterop/IDispatchComObject.cs | 2 +- .../RuntimeBinder/Semantics/Binding/Better.cs | 2 +- .../Semantics/GroupToArgsBinder.cs | 5 +- .../RuntimeBinder/Semantics/Operators.cs | 28 +- .../Semantics/Symbols/AggregateSymbol.cs | 6 +- .../CSharp/RuntimeBinder/SymbolTable.cs | 2 +- .../Diagnostics/Tracing/StubEnvironment.cs | 2 +- .../src/ConfigurationBinder.cs | 146 +- ...oft.Extensions.Configuration.Binder.csproj | 9 +- .../src/Resources/Strings.resx | 19 +- .../tests/ConfigurationBinderTests.cs | 664 +--- ...tensions.Configuration.Binder.Tests.csproj | 1 - .../src/ServiceProvider.cs | 2 +- .../PatternContexts/PatternContextLinear.cs | 2 +- .../Microsoft.Extensions.Hosting.Systemd.cs | 13 +- .../src/SystemdHostBuilderExtensions.cs | 67 +- .../tests/UseSystemdTests.cs | 26 +- ...soft.Extensions.Hosting.WindowsServices.cs | 6 +- ...owsServiceLifetimeHostBuilderExtensions.cs | 123 +- ...sions.Hosting.WindowsServices.Tests.csproj | 9 +- .../tests/UseWindowsServiceTests.cs | 93 +- .../src/HostingHostBuilderExtensions.cs | 18 +- .../tests/UnitTests/HostTests.cs | 32 - ...osoft.Extensions.Hosting.Unit.Tests.csproj | 2 +- .../Microsoft.Extensions.Logging.Console.cs | 7 - .../src/ConsoleLoggerOptions.cs | 37 - .../src/ConsoleLoggerProcessor.cs | 166 +- .../src/ConsoleLoggerProvider.cs | 18 +- .../src/ConsoleLoggerQueueFullMode.cs | 20 - ...icrosoft.Extensions.Logging.Console.csproj | 2 - .../src/Resources/Strings.resx | 9 - .../src/SimpleConsoleFormatter.cs | 2 +- .../ConsoleFormatterTests.cs | 4 +- .../ConsoleLoggerExtensionsTests.cs | 45 +- .../ConsoleLoggerProcessorTests.cs | 175 - .../ConsoleLoggerTest.cs | 93 +- ...ft.Extensions.Logging.Console.Tests.csproj | 1 - .../src/TraceSourceLoggerProvider.cs | 7 +- .../src/OptionsManager.cs | 2 +- .../src/OptionsMonitor.cs | 2 +- .../src/runtime.compatibility.json | 26 +- .../src/runtime.json | 19 +- .../src/runtimeGroups.props | 6 +- .../src/Microsoft/Win32/SystemEvents.cs | 8 +- .../src/Sgen.cs | 6 +- .../Collections/Concurrent/ConcurrentBag.cs | 4 +- .../src/System.Collections.Immutable.csproj | 3 +- .../Immutable/ImmutableArray_1.Builder.cs | 10 +- .../Collections/Immutable/ImmutableArray_1.cs | 4 +- .../Immutable/ImmutableList_1.Node.cs | 6 +- .../Specialized/NameObjectCollectionBase.cs | 4 +- .../Specialized/NameValueCollection.cs | 2 +- .../System/Collections/Generic/LinkedList.cs | 2 +- .../System.Collections/tests/default.rd.xml | 6 - .../AttributedExportDefinition.cs | 4 +- .../Composition/ContractNameServices.cs | 2 +- .../Hosting/AggregateExportProvider.cs | 2 +- .../Composition/Hosting/AssemblyCatalog.cs | 2 - .../Composition/Hosting/AtomicComposition.cs | 2 +- .../ComposablePartCatalogCollection.cs | 14 +- .../Hosting/CompositionContainer.cs | 2 +- .../Composition/Hosting/DirectoryCatalog.cs | 12 +- .../Composition/ImportAttribute.cs | 2 +- .../Composition/ReflectionModel/ImportType.cs | 2 +- .../ReflectionModelServices.cs | 2 +- .../Linq/ComponentModel/XComponentModel.cs | 6 +- .../DesigntimeLicenseContextSerializer.cs | 2 +- .../DesignTimeVisibleAttribute.cs | 6 +- .../System/ComponentModel/TypeDescriptor.cs | 2 + .../Hosting/Core/CompositionContract.cs | 4 +- .../Composition/TypedParts/ContractHelpers.cs | 6 +- .../TypedParts/Discovery/DiscoveredPart.cs | 3 +- .../TypedParts/Discovery/TypeInspector.cs | 2 +- .../Configuration/ApplicationSettingsBase.cs | 2 +- .../System/Configuration/ClientConfigPaths.cs | 3 +- .../Configuration/ConfigDefinitionUpdates.cs | 4 +- .../Configuration/ConfigurationElement.cs | 4 +- .../ConfigurationElementCollection.cs | 2 +- .../StringAttributeCollection.cs | 2 +- .../System.Console/src/System.Console.csproj | 2 - .../src/System/ConsolePal.Unix.cs | 47 +- .../System.Console/src/System/TermInfo.cs | 5 +- .../src/System/Data/Common/ByteStorage.cs | 2 +- .../System/Data/Common/DBCommandBuilder.cs | 5 +- .../System/Data/Common/DataRecordInternal.cs | 4 +- .../System/Data/Common/DbConnectionOptions.cs | 2 +- .../src/System/Data/Common/DecimalStorage.cs | 2 +- .../src/System/Data/Common/DoubleStorage.cs | 2 +- .../src/System/Data/Common/Int16Storage.cs | 2 +- .../src/System/Data/Common/Int32Storage.cs | 2 +- .../src/System/Data/Common/Int64Storage.cs | 2 +- .../src/System/Data/Common/SByteStorage.cs | 2 +- .../Data/Common/SQLTypes/SQLByteStorage.cs | 2 +- .../Data/Common/SQLTypes/SQLDecimalStorage.cs | 2 +- .../Data/Common/SQLTypes/SQLDoubleStorage.cs | 2 +- .../Data/Common/SQLTypes/SQLInt16Storage.cs | 2 +- .../Data/Common/SQLTypes/SQLInt32Storage.cs | 2 +- .../Data/Common/SQLTypes/SQLInt64Storage.cs | 2 +- .../Data/Common/SQLTypes/SQLMoneyStorage.cs | 2 +- .../Data/Common/SQLTypes/SQLSingleStorage.cs | 2 +- .../Data/Common/SQLTypes/SQLStringStorage.cs | 4 +- .../src/System/Data/Common/SingleStorage.cs | 2 +- .../src/System/Data/Common/StringStorage.cs | 4 +- .../src/System/Data/Common/UInt16Storage.cs | 2 +- .../src/System/Data/Common/UInt32Storage.cs | 2 +- .../src/System/Data/Common/UInt64Storage.cs | 2 +- .../src/System/Data/ConstraintCollection.cs | 3 +- .../src/System/Data/ConstraintEnumerator.cs | 2 +- .../src/System/Data/DataColumn.cs | 4 +- .../Data/DataColumnPropertyDescriptor.cs | 13 +- .../src/System/Data/DataRelation.cs | 5 +- .../Data/DataRelationPropertyDescriptor.cs | 12 +- .../src/System/Data/DataTable.cs | 6 +- .../Data/DataTablePropertyDescriptor.cs | 12 +- .../src/System/Data/DataView.cs | 6 +- .../src/System/Data/Filter/BinaryNode.cs | 5 +- .../src/System/Data/Filter/DataExpression.cs | 2 +- .../src/System/Data/Filter/FunctionNode.cs | 2 +- .../src/System/Data/Filter/UnaryNode.cs | 2 +- .../src/System/Data/LinqDataView.cs | 2 +- .../Data/ProviderBase/DataReaderContainer.cs | 2 +- .../src/System/Data/SQLTypes/SQLBinary.cs | 4 +- .../src/System/Data/SQLTypes/SQLBoolean.cs | 4 +- .../src/System/Data/SQLTypes/SQLByte.cs | 4 +- .../src/System/Data/SQLTypes/SQLDateTime.cs | 4 +- .../src/System/Data/SQLTypes/SQLDecimal.cs | 13 +- .../src/System/Data/SQLTypes/SQLDouble.cs | 4 +- .../src/System/Data/SQLTypes/SQLGuid.cs | 24 +- .../src/System/Data/SQLTypes/SQLInt16.cs | 4 +- .../src/System/Data/SQLTypes/SQLInt32.cs | 4 +- .../src/System/Data/SQLTypes/SQLInt64.cs | 4 +- .../src/System/Data/SQLTypes/SQLMoney.cs | 6 +- .../src/System/Data/SQLTypes/SQLSingle.cs | 4 +- .../src/System/Data/SQLTypes/SQLString.cs | 6 +- .../src/System/Data/Selection.cs | 2 +- .../src/System/Data/SimpleType.cs | 4 +- .../src/System/Data/XMLSchema.cs | 46 +- .../src/System/Data/XmlDataLoader.cs | 5 +- .../src/System/Data/xmlsaver.cs | 16 +- .../src/System/Xml/DataPointer.cs | 2 +- .../src/System/Xml/XPathNodePointer.cs | 2 +- .../src/System/Xml/XmlDataDocument.cs | 24 +- .../System/Data/Common/DBConnectionString.cs | 2 +- .../System/Data/Common/DbConnectionOptions.cs | 14 +- .../Data/ProviderBase/DbConnectionPool.cs | 12 +- .../src/System/Data/Odbc/Odbc32.cs | 2 +- .../src/System/Data/Odbc/OdbcCommand.cs | 3 +- .../src/System/Data/Odbc/OdbcConnection.cs | 2 +- .../System/Data/Odbc/OdbcConnectionHelper.cs | 4 +- .../src/System/Data/Odbc/OdbcDataReader.cs | 12 +- .../src/System/Data/Odbc/OdbcError.cs | 4 +- .../System/Data/Odbc/OdbcMetaDataFactory.cs | 18 +- .../src/System/Data/Odbc/OdbcParameter.cs | 3 +- .../System/Data/Odbc/OdbcParameterHelper.cs | 7 +- .../System.Data.OleDb/src/ColumnBinding.cs | 2 +- .../src/DbConnectionOptions.cs | 7 +- .../src/DbParameterHelper.cs | 3 +- .../System.Data.OleDb/src/OleDbCommand.cs | 3 +- .../src/OleDbCommandBuilder.cs | 4 +- .../System.Data.OleDb/src/OleDbConnection.cs | 11 +- .../src/OleDbConnectionInternal.cs | 3 +- .../System.Data.OleDb/src/OleDbDataReader.cs | 4 +- .../System.Data.OleDb/src/OleDbError.cs | 9 +- .../System.Data.OleDb/src/OleDbException.cs | 3 +- .../System.Data.OleDb/src/OleDbParameter.cs | 3 +- .../System.Data.OleDb/src/OleDbStruct.cs | 9 +- .../System.Data.OleDb/src/RowBinding.cs | 4 +- .../src/System/Data/Common/AdapterUtil.cs | 4 +- .../Data/ProviderBase/DbConnectionHelper.cs | 7 +- .../Data/ProviderBase/DbConnectionPool.cs | 5 +- .../Data/ProviderBase/DbMetaDataFactory.cs | 12 +- .../Diagnostics/Activity.DateTime.corefx.cs | 2 + .../DiagnosticSourceEventSource.cs | 3 - .../Diagnostics/Metrics/MetricsEventSource.cs | 2 +- .../src/System.Diagnostics.EventLog.csproj | 4 +- .../System/Diagnostics/Reader/EventKeyword.cs | 4 +- .../System/Diagnostics/Reader/EventLevel.cs | 4 +- .../Diagnostics/Reader/EventLogException.cs | 35 +- .../System/Diagnostics/Reader/EventLogLink.cs | 4 +- .../Diagnostics/Reader/EventLogReader.cs | 2 +- .../Diagnostics/Reader/EventLogRecord.cs | 4 +- .../Diagnostics/Reader/EventLogWatcher.cs | 5 +- .../Diagnostics/Reader/EventMetadata.cs | 2 +- .../System/Diagnostics/Reader/EventOpcode.cs | 2 +- .../System/Diagnostics/Reader/EventTask.cs | 2 +- .../Diagnostics/Reader/NativeWrapper.cs | 15 +- .../Reader/EventLogSessionTests.cs | 12 - .../Diagnostics/FileVersionInfo.Unix.cs | 13 +- .../Diagnostics/FileVersionInfo.Windows.cs | 4 +- .../Diagnostics/SharedPerformanceCounter.cs | 4 +- .../src/System.Diagnostics.Process.csproj | 2 + .../src/System/Diagnostics/Process.NonUap.cs | 2 +- .../src/System/Diagnostics/Process.Unix.cs | 12 +- .../Diagnostics/ProcessManager.Win32.cs | 57 +- .../tests/ProcessTests.Unix.cs | 18 +- .../tests/ProcessTests.Windows.cs | 3 + .../tests/ProcessTests.cs | 6 +- .../src/System/Diagnostics/Switch.cs | 6 +- .../src/System/Diagnostics/TraceListener.cs | 4 +- .../TrimmingTests/EventSourceManifestTest.cs | 3 - .../AccountManagement/AD/ADAMStoreCtx.cs | 4 +- .../AccountManagement/AD/ADDNLinkedAttrSet.cs | 8 +- .../AccountManagement/AD/ADStoreCtx.cs | 18 +- .../AD/ADStoreCtx_LoadStore.cs | 4 +- .../AccountManagement/AD/ADStoreCtx_Query.cs | 9 +- .../AccountManagement/AD/RangeRetriever.cs | 2 +- .../AccountManagement/AD/SDSCache.cs | 6 +- .../AccountManagement/AD/SDSUtils.cs | 12 +- .../AccountManagement/AD/SidList.cs | 2 +- .../AuthenticablePrincipal.cs | 2 +- .../AccountManagement/ExtensionCache.cs | 10 +- .../AccountManagement/FindResultEnumerator.cs | 4 +- .../AccountManagement/PasswordInfo.cs | 2 +- .../AccountManagement/Principal.cs | 12 +- .../AccountManagement/PrincipalCollection.cs | 4 +- .../PrincipalCollectionEnumerator.cs | 2 +- .../AccountManagement/PrincipalSearcher.cs | 4 +- .../AccountManagement/SAM/SAMMembersSet.cs | 4 +- .../AccountManagement/SAM/SAMStoreCtx.cs | 8 +- .../AccountManagement/StoreCtx.cs | 6 +- .../TrackedCollectionEnumerator.cs | 2 +- .../AccountManagement/Utils.cs | 6 +- .../AccountManagement/interopt.cs | 10 +- .../Protocols/ldap/LdapConnection.cs | 2 +- .../ActiveDirectorySchemaClass.cs | 4 +- .../ActiveDirectorySchemaProperty.cs | 10 +- .../ActiveDirectory/ActiveDirectorySite.cs | 2 +- .../ActiveDirectorySiteLink.cs | 2 +- .../ActiveDirectorySiteLinkCollection.cs | 2 +- .../ActiveDirectory/ActiveDirectorySubnet.cs | 2 +- .../ActiveDirectory/ConfigSet.cs | 4 +- .../ActiveDirectory/DomainController.cs | 2 +- .../ForestTrustRelationshipInformation.cs | 2 +- .../ActiveDirectory/Locator.cs | 2 +- .../ActiveDirectory/ReplicationConnection.cs | 4 +- .../TrustRelationshipInformation.cs | 2 +- .../ActiveDirectory/Utils.cs | 6 +- .../DirectoryServices/DirectoryEntry.cs | 24 +- .../DirectoryServices/DirectorySearcher.cs | 14 +- .../src/System/Drawing/ClientUtils.cs | 4 +- .../src/System/Drawing/FontConverter.cs | 8 +- .../src/System/Drawing/Image.cs | 2 + .../src/System/Drawing/ImageAnimator.cs | 9 +- .../src/System/Drawing/ImageInfo.cs | 5 +- .../Drawing/Imaging/EncoderParameter.cs | 10 +- .../Drawing/Imaging/ImageCodecInfoPrivate.cs | 4 +- .../Drawing/Imaging/MetafileHeaderEmf.cs | 10 +- .../Drawing/Imaging/MetafileHeaderWmf.cs | 10 +- .../src/System/Drawing/Printing/PaperSize.cs | 2 +- .../src/System/Drawing/StringFormat.cs | 2 +- .../ref/System.Formats.Tar.cs | 17 +- .../src/Resources/Strings.resx | 9 +- .../src/System.Formats.Tar.csproj | 2 +- .../src/System/Formats/Tar/GnuTarEntry.cs | 57 +- .../PaxGlobalExtendedAttributesTarEntry.cs | 50 - .../src/System/Formats/Tar/PaxTarEntry.cs | 78 +- .../src/System/Formats/Tar/PosixTarEntry.cs | 35 +- .../src/System/Formats/Tar/TarEntry.Unix.cs | 3 +- .../src/System/Formats/Tar/TarEntry.cs | 124 +- .../src/System/Formats/Tar/TarFile.cs | 5 +- .../src/System/Formats/Tar/TarHeader.Read.cs | 167 +- .../src/System/Formats/Tar/TarHeader.Write.cs | 74 +- .../src/System/Formats/Tar/TarHeader.cs | 11 +- .../src/System/Formats/Tar/TarHelpers.cs | 107 +- .../src/System/Formats/Tar/TarReader.cs | 102 +- .../src/System/Formats/Tar/TarWriter.Unix.cs | 7 +- .../System/Formats/Tar/TarWriter.Windows.cs | 6 +- .../src/System/Formats/Tar/TarWriter.cs | 100 +- .../src/System/Formats/Tar/UstarTarEntry.cs | 23 +- .../src/System/Formats/Tar/V7TarEntry.cs | 14 +- .../tests/CompressedTar.Tests.cs | 2 +- .../tests/System.Formats.Tar.Tests.csproj | 9 - .../TarEntry/GnuTarEntry.Conversion.Tests.cs | 262 -- .../TarEntry/PaxTarEntry.Conversion.Tests.cs | 345 -- .../TarEntry.Conversion.Tests.Base.cs | 223 -- .../tests/TarEntry/TarEntryV7.Tests.cs | 1 - .../UstarTarEntry.Conversion.Tests.cs | 262 -- .../TarEntry/V7TarEntry.Conversion.Tests.cs | 236 -- .../TarFile.ExtractToDirectory.File.Tests.cs | 23 - ...TarFile.ExtractToDirectory.Stream.Tests.cs | 46 +- .../TarReader.ExtractToFile.Tests.Unix.cs | 45 - .../TarReader.ExtractToFile.Tests.cs | 50 +- ...der.File.GlobalExtendedAttributes.Tests.cs | 86 - .../TarReader/TarReader.File.Tests.Base.cs | 620 --- .../tests/TarReader/TarReader.File.Tests.cs | 730 +++- .../tests/TarTestsBase.Gnu.cs | 2 +- .../tests/TarTestsBase.Pax.cs | 42 +- .../System.Formats.Tar/tests/TarTestsBase.cs | 62 +- .../tests/TarWriter/TarWriter.Tests.cs | 19 +- .../TarWriter.WriteEntry.Entry.Gnu.Tests.cs | 9 +- .../TarWriter.WriteEntry.Entry.Pax.Tests.cs | 281 +- .../TarWriter.WriteEntry.Entry.Ustar.Tests.cs | 9 +- .../TarWriter.WriteEntry.Entry.V7.Tests.cs | 49 +- .../TarWriter.WriteEntry.File.Tests.Unix.cs | 29 +- ...TarWriter.WriteEntry.File.Tests.Windows.cs | 43 +- .../TarWriter.WriteEntry.File.Tests.cs | 62 +- .../TarWriter/TarWriter.WriteEntry.Tests.cs | 203 - .../IdnMappingIdnaConformanceTests.cs | 4 + .../NumberFormatInfo/NumberFormatInfoTests.cs | 16 - ...Extensions.ZipArchiveEntry.Extract.Unix.cs | 4 +- .../ref/System.IO.Compression.cs | 11 +- .../Compression/DeflateManaged/InputBuffer.cs | 2 +- .../System/IO/Compression/ZipArchiveEntry.cs | 32 +- .../tests/ZipArchive/zip_ReadTests.cs | 42 - .../AccessControl/DirectoryObjectSecurity.cs | 4 +- .../src/System/IO/FileSystemWatcher.Linux.cs | 39 +- .../src/System/IO/FileSystemWatcher.cs | 2 +- .../tests/Base/AllGetSetAttributes.cs | 10 +- .../tests/Base/BaseGetSetUnixFileMode.cs | 217 -- .../tests/Base/FileGetSetAttributes.cs | 4 +- .../CreateDirectory_UnixFileMode.Unix.cs | 57 - .../CreateDirectory_UnixFileMode.Windows.cs | 17 - .../tests/Directory/Delete.cs | 1 + .../tests/Directory/Move.cs | 1 + .../tests/DirectoryInfo/GetSetUnixFileMode.cs | 20 - .../tests/DirectoryInfo/MoveTo.cs | 1 + .../tests/File/GetSetUnixFileMode.cs | 16 - .../File/GetSetUnixFileMode_SafeFileHandle.cs | 25 - .../System.IO.FileSystem/tests/File/Open.cs | 12 - .../tests/File/ReadWriteAllBytes.cs | 1 + .../tests/File/ReadWriteAllBytesAsync.cs | 1 + .../tests/File/ReadWriteAllLines.cs | 2 + .../tests/File/ReadWriteAllLinesAsync.cs | 1 + .../tests/File/ReadWriteAllText.cs | 1 + .../tests/File/ReadWriteAllTextAsync.cs | 1 + .../tests/FileInfo/GetSetUnixFileMode.cs | 16 - .../tests/FileInfo/Open.cs | 12 - .../tests/FileStream/FileStreamOptions.cs | 26 - .../tests/FileStream/ctor_options.Unix.cs | 59 - .../tests/FileStream/ctor_options.cs | 13 - .../tests/FileSystemTest.cs | 48 - .../tests/System.IO.FileSystem.Tests.csproj | 7 - .../src/System.IO.MemoryMappedFiles.csproj | 2 + .../MemoryMappedFile.Unix.cs | 8 +- .../MemoryMappedFile.CreateFromFile.Tests.cs | 2 + .../src/System/IO/Packaging/PackUriHelper.cs | 2 +- .../src/System/IO/Packaging/Package.cs | 10 +- .../src/System/IO/Packaging/PackagePart.cs | 2 +- .../src/System/IO/Packaging/ZipPackage.cs | 32 +- .../System/IO/Packaging/ZipStreamManager.cs | 25 +- .../src/System.IO.Pipes.csproj | 2 + .../src/System/IO/Pipes/PipeStream.Windows.cs | 6 +- .../src/System/IO/Ports/SerialPort.cs | 2 + .../src/System/IO/Ports/SerialStream.Unix.cs | 22 +- .../System/IO/Ports/SerialStream.Windows.cs | 16 +- .../System/Dynamic/BinaryOperationBinder.cs | 4 +- .../src/System/Dynamic/ConvertBinder.cs | 4 +- .../System/Dynamic/CreateInstanceBinder.cs | 4 +- .../src/System/Dynamic/DeleteIndexBinder.cs | 4 +- .../src/System/Dynamic/DeleteMemberBinder.cs | 4 +- .../src/System/Dynamic/GetIndexBinder.cs | 4 +- .../src/System/Dynamic/GetMemberBinder.cs | 4 +- .../src/System/Dynamic/InvokeBinder.cs | 4 +- .../src/System/Dynamic/InvokeMemberBinder.cs | 4 +- .../src/System/Dynamic/SetIndexBinder.cs | 4 +- .../src/System/Dynamic/SetMemberBinder.cs | 4 +- .../System/Dynamic/UnaryOperationBinder.cs | 4 +- .../Compiler/LambdaCompiler.Statements.cs | 2 +- .../Linq/Expressions/DebugViewWriter.cs | 15 +- .../Interpreter/InstructionList.cs | 3 +- .../Expressions/Interpreter/LightCompiler.cs | 2 +- .../Coalesce/BinaryCoalesceTests.cs | 2 +- .../tests/CompilerTests.cs | 2 +- .../tests/StackSpillerTests.cs | 42 +- ...aryArithmeticNegateCheckedNullableTests.cs | 2 +- .../tests/default.rd.xml | 18 - .../Partitioning/PartitionedDataSource.cs | 2 +- .../QueryOperators/BinaryQueryOperator.cs | 2 +- .../Parallel/QueryOperators/QuerySettings.cs | 2 +- .../QueryOperators/Unary/SortQueryOperator.cs | 2 +- .../QueryOperators/UnaryQueryOperator.cs | 2 +- .../src/System/Linq/ParallelEnumerable.cs | 4 +- .../src/System/Management/ManagementClass.cs | 2 +- .../System/Management/ManagementDateTime.cs | 30 +- .../System/Management/ManagementEventArgs.cs | 2 +- .../ManagementNamedValueCollection.cs | 3 +- .../src/System/Management/ManagementObject.cs | 27 +- .../Management/ManagementObjectCollection.cs | 4 +- .../Management/ManagementObjectSearcher.cs | 6 +- .../System/Management/ManagementOptions.cs | 35 +- .../src/System/Management/ManagementPath.cs | 5 +- .../src/System/Management/ManagementQuery.cs | 43 +- .../src/System/Management/ManagementScope.cs | 7 +- .../src/System/Management/Method.cs | 2 +- .../src/System/Management/Property.cs | 2 +- .../src/System/Management/PropertySet.cs | 4 +- .../src/System/Management/Qualifier.cs | 2 +- .../src/System/Management/QualifierSet.cs | 8 +- .../src/System/Management/WMIGenerator.cs | 94 +- .../src/System/Buffers/Text/Base64Decoder.cs | 109 +- .../src/System/Buffers/Text/Base64Encoder.cs | 88 +- .../tests/Base64/Base64TestHelper.cs | 2 +- .../ref/System.Net.Http.Json.cs | 20 - .../src/System.Net.Http.Json.csproj | 1 - .../Json/HttpClientJsonExtensions.Delete.cs | 179 - .../HttpClientJsonExtensionsTests.cs | 46 - ...ttpClientHandlerTestBase.WinHttpHandler.cs | 4 +- .../FunctionalTests/PlatformHandlerTest.cs | 5 +- .../src/Resources/Strings.resx | 40 +- .../src/System.Net.Http.csproj | 97 + .../Http/Headers/AuthenticationHeaderValue.cs | 18 +- .../Net/Http/Headers/BaseHeaderParser.cs | 2 +- .../Http/Headers/CacheControlHeaderValue.cs | 8 +- .../Headers/ContentDispositionHeaderValue.cs | 2 +- .../Http/Headers/ContentRangeHeaderValue.cs | 20 +- .../Net/Http/Headers/EntityTagHeaderValue.cs | 6 +- .../Net/Http/Headers/HeaderUtilities.cs | 4 +- .../Net/Http/Headers/MediaTypeHeaderValue.cs | 6 +- .../Net/Http/Headers/NameValueHeaderValue.cs | 18 +- .../NameValueWithParametersHeaderValue.cs | 2 +- .../Net/Http/Headers/ProductHeaderValue.cs | 10 +- .../Http/Headers/ProductInfoHeaderParser.cs | 2 +- .../Http/Headers/ProductInfoHeaderValue.cs | 6 +- .../Http/Headers/RangeConditionHeaderValue.cs | 2 +- .../Net/Http/Headers/RangeHeaderValue.cs | 8 +- .../Net/Http/Headers/RangeItemHeaderValue.cs | 12 +- .../Http/Headers/RetryConditionHeaderValue.cs | 4 +- .../Headers/StringWithQualityHeaderValue.cs | 14 +- .../Http/Headers/TransferCodingHeaderValue.cs | 2 +- .../System/Net/Http/Headers/ViaHeaderValue.cs | 20 +- .../Net/Http/Headers/WarningHeaderValue.cs | 16 +- .../System/Net/Http/HttpResponseMessage.cs | 14 +- .../src/System/Net/Http/HttpRuleParser.cs | 2 +- .../src/System/Net/Http/MultipartContent.cs | 8 - .../AuthenticationHelper.NtAuth.cs | 74 +- .../AuthenticationHelper.NtAuth.tvOS.cs | 30 + .../ChunkedEncodingWriteStream.cs | 2 +- .../Http/SocketsHttpHandler/ConnectHelper.cs | 16 +- .../SocketsHttpHandler/Http2Connection.cs | 2 +- .../SocketsHttpHandler/Http3Connection.cs | 2 +- .../SocketsHttpHandler/Http3RequestStream.cs | 8 +- .../Http/SocketsHttpHandler/HttpConnection.cs | 22 +- .../SocketsHttpHandler/HttpConnectionPool.cs | 8 +- .../HttpConnectionSettings.cs | 10 + .../src/System/Net/Http/StreamContent.cs | 52 +- .../HttpClientAuthenticationTest.cs | 1 + .../HttpClientHandlerTest.AltSvc.cs | 20 +- .../HttpClientHandlerTest.Finalization.cs | 5 + .../HttpClientHandlerTest.Http3.cs | 115 +- ...lientHandlerTestBase.SocketsHttpHandler.cs | 44 +- .../HttpClientMiniStressTest.cs | 16 +- .../FunctionalTests/NtAuthTests.FakeServer.cs | 140 - .../FunctionalTests/NtAuthTests.Windows.cs | 21 +- .../ReadOnlyMemoryContentTest.cs | 237 +- .../ResponseStreamZeroByteReadTests.cs | 19 +- .../FunctionalTests/SocketsHttpHandlerTest.cs | 123 +- .../FunctionalTests/StreamContentTest.cs | 103 +- .../System.Net.Http.Functional.Tests.csproj | 114 +- .../tests/FunctionalTests/TelemetryTest.cs | 60 +- .../src/Resources/Strings.resx | 3 - .../Net/Managed/HttpResponseStream.Managed.cs | 2 +- .../WebSockets/HttpWebSocket.Managed.cs | 2 +- .../Net/Windows/HttpListener.Windows.cs | 17 +- .../Windows/HttpListenerContext.Windows.cs | 2 +- .../Net/Windows/HttpResponseStream.Windows.cs | 2 +- .../System.Net.Mail/ref/System.Net.Mail.cs | 6 +- .../src/Resources/Strings.resx | 3 - .../src/System/Net/Mail/MailAddress.cs | 12 +- .../src/System/Net/Mail/MailBnfHelper.cs | 23 +- .../src/System/Net/Mail/MailMessage.cs | 4 +- .../src/System/Net/Mail/MailPriority.cs | 2 +- .../src/System/Net/Mail/SmtpConnection.cs | 2 +- .../Net/Mail/SmtpFailedRecipientsException.cs | 2 +- .../src/System/Net/Mime/Base64Encoder.cs | 9 +- .../src/System/Net/Mime/QEncoder.cs | 2 +- .../System/Net/Mime/QuotedPrintableStream.cs | 2 +- .../src/System/Net/Mime/WriteStateInfoBase.cs | 6 +- .../BsdIPGlobalProperties.cs | 2 +- .../SystemIPGlobalProperties.cs | 12 +- .../SystemIPInterfaceProperties.cs | 10 +- .../SystemIPv4InterfaceProperties.cs | 11 +- .../SystemNetworkInterface.cs | 30 +- .../SystemUnicastIPAddressInformation.cs | 12 +- .../UnixIPGlobalProperties.cs | 2 +- .../Net/NetworkInformation/Ping.Windows.cs | 18 +- .../src/System/Net/Cookie.cs | 14 +- .../src/System/Net/IPAddress.cs | 6 +- .../System.Net.Quic/ref/System.Net.Quic.cs | 28 +- .../src/ExcludeApiList.PNSE.txt | 3 +- .../src/System.Net.Quic.csproj | 5 +- .../Implementations/Mock/MockConnection.cs | 484 +++ .../Mock/MockImplementationProvider.cs | 26 + .../Quic/Implementations/Mock/MockListener.cs | 114 + .../Quic/Implementations/Mock/MockStream.cs | 338 ++ .../MsQuic/Internal/MsQuicApi.cs | 37 +- .../Interop/SafeMsQuicConfigurationHandle.cs | 44 +- .../MsQuic/MsQuicConnection.cs | 30 +- .../MsQuic/MsQuicImplementationProvider.cs | 32 + .../Implementations/MsQuic/MsQuicListener.cs | 15 +- .../Implementations/MsQuic/MsQuicStream.cs | 162 +- .../Implementations/QuicConnectionProvider.cs | 37 + .../QuicImplementationProvider.cs | 18 + .../Implementations/QuicListenerProvider.cs | 17 + .../Implementations/QuicStreamProvider.cs | 62 + .../Net/Quic/QuicConnection.Unsupported.cs | 10 - .../src/System/Net/Quic/QuicConnection.cs | 40 +- ...QuicImplementationProviders.Unsupported.cs | 30 + .../Net/Quic/QuicImplementationProviders.cs | 12 + .../Net/Quic/QuicListener.Unsupported.cs | 10 - .../src/System/Net/Quic/QuicListener.cs | 36 +- .../src/System/Net/Quic/QuicStream.cs | 5 +- .../MsQuicCipherSuitesPolicyTests.cs | 13 +- .../MsQuicPlatformDetectionTests.cs | 7 +- .../tests/FunctionalTests/MsQuicTests.cs | 47 +- .../FunctionalTests/QuicConnectionTests.cs | 50 +- .../FunctionalTests/QuicListenerTests.cs | 36 +- ...icStreamConnectedStreamConformanceTests.cs | 42 +- .../tests/FunctionalTests/QuicStreamTests.cs | 38 +- .../tests/FunctionalTests/QuicTestBase.cs | 50 +- .../src/System/Net/FtpControlStream.cs | 9 +- .../src/System/Net/FtpDataStream.cs | 2 +- .../src/System/Net/HttpWebResponse.cs | 5 +- .../src/System/Net/TaskExtensions.cs | 5 +- .../ref/System.Net.Security.cs | 50 - .../src/Resources/Strings.resx | 3 - .../src/System.Net.Security.csproj | 31 +- .../src/System/Net/NTAuthentication.cs | 93 +- .../Net/Security/NegotiateAuthentication.cs | 326 -- .../NegotiateAuthenticationClientOptions.cs | 41 - .../NegotiateAuthenticationServerOptions.cs | 36 - .../NegotiateAuthenticationStatusCode.cs | 63 - ...NegotiateStreamPal.PlatformNotSupported.cs | 6 +- .../Net/Security/NegotiateStreamPal.Unix.cs | 6 + .../Security/NegotiateStreamPal.Windows.cs | 211 +- .../System/Net/Security/SslSessionsCache.cs | 44 +- .../src/System/Net/Security/TlsFrameHelper.cs | 10 +- .../CertificateValidationRemoteServer.cs | 34 +- .../SslAuthenticationOptionsTest.cs | 1 - .../SslStreamNetworkStreamTest.cs | 2 +- .../tests/UnitTests/Fakes}/FakeNtlmServer.cs | 22 +- .../tests/UnitTests/NTAuthenticationTests.cs | 88 + .../UnitTests/NegotiateAuthenticationTests.cs | 254 -- .../System.Net.Security.Unit.Tests.csproj | 6 +- .../src/System/Net/Sockets/Socket.cs | 2 +- .../src/System/Net/Sockets/TCPListener.cs | 2 +- .../Net/WebSockets/WebSocketHandle.Managed.cs | 9 +- .../System/Net/WebSockets/ManagedWebSocket.cs | 2 +- .../Win32/SafeHandles/SafeFileHandle.Unix.cs | 51 +- .../SafeHandles/SafeFileHandle.Windows.cs | 4 +- .../src/Resources/Strings.resx | 47 +- .../System.Private.CoreLib.Shared.projitems | 22 +- .../System.Private.CoreLib/src/System/Byte.cs | 3 + .../System.Private.CoreLib/src/System/Char.cs | 31 + .../Collections/Generic/ArraySortHelper.cs | 4 +- .../Collections/Generic/ValueListBuilder.cs | 21 +- .../src/System/DateTime.Windows.cs | 2 +- .../src/System/Decimal.cs | 49 + .../src/System/DefaultBinder.cs | 7 +- .../System/Diagnostics/Tracing/EventSource.cs | 3 - .../Diagnostics/Tracing/RuntimeEventSource.cs | 4 - .../src/System/Double.cs | 798 +--- .../src/System/Empty.cs | 7 +- .../src/System/Environment.Unix.cs | 8 - .../src/System/Environment.Win32.cs | 27 +- .../src/System/Environment.Windows.cs | 28 - .../src/System/Environment.cs | 7 + .../src/System/Globalization/CultureData.cs | 52 +- .../src/System/Globalization/DateTimeParse.cs | 3 + .../System/Globalization/OrdinalCasing.Icu.cs | 2 +- .../System.Private.CoreLib/src/System/Half.cs | 73 +- .../src/System/IO/Directory.Unix.cs | 24 - .../src/System/IO/Directory.Windows.cs | 11 - .../src/System/IO/Directory.cs | 18 - .../src/System/IO/DirectoryInfo.cs | 2 +- .../Enumeration/FileSystemEnumerator.Unix.cs | 2 +- .../FileSystemEnumerator.Windows.cs | 2 +- .../IO/Enumeration/FileSystemEnumerator.cs | 2 +- .../src/System/IO/File.Unix.cs | 22 - .../src/System/IO/File.Windows.cs | 22 - .../src/System/IO/File.cs | 47 +- .../src/System/IO/FileInfo.cs | 2 +- .../src/System/IO/FileStatus.Unix.cs | 121 +- .../src/System/IO/FileStream.cs | 15 +- .../src/System/IO/FileStreamOptions.cs | 30 - .../src/System/IO/FileSystem.Unix.cs | 48 +- .../src/System/IO/FileSystem.cs | 14 - .../src/System/IO/FileSystemInfo.Unix.cs | 6 - .../src/System/IO/FileSystemInfo.Windows.cs | 8 - .../src/System/IO/FileSystemInfo.cs | 22 - .../src/System/IO/Path.cs | 10 +- .../src/System/IO/RandomAccess.Windows.cs | 28 +- .../AsyncWindowsFileStreamStrategy.cs | 4 +- .../IO/Strategies/FileStreamHelpers.Unix.cs | 4 +- .../Strategies/FileStreamHelpers.Windows.cs | 6 +- .../System/IO/Strategies/FileStreamHelpers.cs | 4 +- .../IO/Strategies/OSFileStreamStrategy.cs | 6 +- .../SyncWindowsFileStreamStrategy.cs | 4 +- .../IO/Strategies/UnixFileStreamStrategy.cs | 4 +- .../src/System/IO/UnixFileMode.cs | 65 - .../src/System/Int16.cs | 3 + .../src/System/Int32.cs | 3 + .../src/System/Int64.cs | 3 + .../src/System/IntPtr.cs | 3 + .../src/System/LocalAppContextSwitches.cs | 14 - .../System.Private.CoreLib/src/System/Math.cs | 42 +- .../src/System/MathF.cs | 8 +- .../src/System/Net/WebUtility.cs | 19 +- .../src/System/Numerics/IAdditionOperators.cs | 2 +- .../src/System/Numerics/IBinaryInteger.cs | 30 +- .../System/Numerics/IDecrementOperators.cs | 2 +- .../src/System/Numerics/IDivisionOperators.cs | 2 +- .../System/Numerics/IExponentialFunctions.cs | 8 +- .../src/System/Numerics/IFloatingPoint.cs | 12 +- .../System/Numerics/IFloatingPointIeee754.cs | 4 +- .../System/Numerics/IHyperbolicFunctions.cs | 2 +- .../System/Numerics/IIncrementOperators.cs | 2 +- .../System/Numerics/ILogarithmicFunctions.cs | 8 +- .../src/System/Numerics/IMultiplyOperators.cs | 2 +- .../src/System/Numerics/INumber.cs | 115 +- .../src/System/Numerics/INumberBase.cs | 6 +- .../src/System/Numerics/IPowerFunctions.cs | 2 +- .../src/System/Numerics/IRootFunctions.cs | 18 +- .../System/Numerics/ISubtractionOperators.cs | 2 +- .../Numerics/ITrigonometricFunctions.cs | 68 +- .../Numerics/IUnaryNegationOperators.cs | 2 +- .../src/System/Random.cs | 2 +- .../src/System/Reflection/AssemblyName.cs | 2 - .../System/Reflection/ConstructorInvoker.cs | 17 +- .../System/Reflection/Emit/TypeNameBuilder.cs | 11 +- .../System/Reflection/MethodInfo.Internal.cs | 7 +- .../Reflection/SignatureTypeExtensions.cs | 8 +- .../src/System/Resources/ResourceReader.cs | 2 - .../System/Resources/RuntimeResourceSet.cs | 3 - .../Runtime/InteropServices/Architecture.cs | 1 - .../Runtime/InteropServices/ComWrappers.cs | 2 +- .../System/Runtime/InteropServices/NFloat.cs | 101 +- .../InteropServices/RuntimeInformation.cs | 2 - .../src/System/SByte.cs | 3 + .../src/System/Single.cs | 607 +-- .../src/System/SpanHelpers.Byte.cs | 7 +- .../src/System/SpanHelpers.Char.cs | 7 +- .../src/System/SpanHelpers.cs | 19 +- .../src/System/Text/ASCIIUtility.cs | 4 +- .../src/System/Text/Latin1Encoding.cs | 37 +- ...ntSource.PortableThreadPool.NativeSinks.cs | 17 - ...veRuntimeEventSource.PortableThreadPool.cs | 39 - .../PortableThreadPool.ThreadCounts.cs | 51 +- .../PortableThreadPool.WorkerThread.cs | 30 +- .../System/Threading/PortableThreadPool.cs | 28 - .../Threading/ThreadInt64PersistentCounter.cs | 50 +- .../TimeZoneInfo.FullGlobalizationData.cs | 27 +- .../src/System/UInt128.cs | 24 +- .../src/System/UInt16.cs | 3 + .../src/System/UInt32.cs | 3 + .../src/System/UInt64.cs | 3 + .../src/System/UIntPtr.cs | 3 + .../src/System/UnitySerializationHolder.cs | 2 + .../Runtime/Serialization/AccessorBuilder.cs | 6 +- .../Serialization/ClassDataContract.cs | 31 +- .../Runtime/Serialization/CodeGenerator.cs | 9 +- .../Serialization/CollectionDataContract.cs | 23 +- .../Runtime/Serialization/DataContract.cs | 41 +- .../Serialization/DataContractSerializer.cs | 28 +- .../DataContractSurrogateCaller.cs | 12 +- .../Serialization/ExtensionDataReader.cs | 2 +- .../Json/DataContractJsonSerializer.cs | 29 +- .../Json/JsonFormatReaderGenerator.cs | 17 +- .../Json/JsonFormatWriterGenerator.cs | 15 +- .../Serialization/Json/JsonWriterDelegator.cs | 2 +- .../Serialization/Json/JsonXmlDataContract.cs | 4 +- .../Serialization/PrimitiveDataContract.cs | 4 - .../Runtime/Serialization/SchemaExporter.cs | 5 +- .../Runtime/Serialization/ScopedKnownTypes.cs | 8 +- .../Serialization/SurrogateDataContract.cs | 12 +- .../Runtime/Serialization/XmlDataContract.cs | 28 +- .../Serialization/XmlObjectSerializer.cs | 24 +- .../XmlObjectSerializerContext.cs | 20 +- .../XmlObjectSerializerReadContext.cs | 26 +- .../XmlObjectSerializerWriteContext.cs | 4 +- .../Serialization/XmlSerializableServices.cs | 8 +- .../Serialization/XmlWriterDelegator.cs | 8 +- .../src/System/Text/Base64Encoding.cs | 15 +- .../src/System/Text/BinHexEncoding.cs | 4 +- .../src/System/Xml/ArrayHelper.cs | 5 +- .../src/System/Xml/PrefixHandle.cs | 2 +- .../src/System/Xml/XmlBaseReader.cs | 4 +- .../src/System/Xml/XmlBaseWriter.cs | 4 +- .../src/System/Xml/XmlBinaryWriter.cs | 46 +- .../src/System/Xml/XmlDictionaryReader.cs | 2 +- .../src/System/Xml/XmlDictionaryWriter.cs | 2 +- .../src/System/Xml/XmlUTF8TextReader.cs | 44 +- .../src/System/Xml/XmlUTF8TextWriter.cs | 34 +- .../System.Private.Uri/src/System/Uri.cs | 5 +- .../System.Private.Uri/src/System/UriExt.cs | 8 +- .../src/System/Xml/Linq/XContainer.cs | 3 +- .../src/System/Xml/Linq/XElement.cs | 2 +- .../src/System/Xml/Linq/XNodeReader.cs | 2 +- .../src/System/Xml/Linq/XObject.cs | 10 +- .../src/System/Xml/XPath/XNodeNavigator.cs | 2 +- .../System.Private.Xml/src/Misc/HResults.cs | 2 + .../src/System/Xml/BinaryXml/SqlUtils.cs | 13 +- .../System/Xml/BinaryXml/XmlBinaryReader.cs | 18 +- .../Xml/Core/HtmlEncodedRawTextWriter.cs | 16 +- .../src/System/Xml/Core/QueryOutputWriter.cs | 15 +- .../System/Xml/Core/XmlAutoDetectWriter.cs | 17 +- .../Xml/Core/XmlEncodedRawTextWriter.cs | 36 +- .../Xml/Core/XmlEncodedRawTextWriterAsync.cs | 36 +- .../src/System/Xml/Core/XmlParserContext.cs | 24 +- .../src/System/Xml/Core/XmlTextReaderImpl.cs | 22 +- .../System/Xml/Core/XmlTextReaderImplAsync.cs | 11 +- .../src/System/Xml/Core/XmlTextWriter.cs | 2 +- .../System/Xml/Core/XmlWellFormedWriter.cs | 6 +- .../System/Xml/Core/XsdValidatingReader.cs | 4 +- .../Xml/Core/XsdValidatingReaderAsync.cs | 2 +- .../src/System/Xml/DiagnosticsSwitches.cs | 4 +- .../System/Xml/Dom/DocumentSchemaValidator.cs | 2 +- .../src/System/Xml/Dom/XPathNodeList.cs | 10 +- .../src/System/Xml/Dom/XmlDeclaration.cs | 2 +- .../src/System/Xml/Dom/XmlDocument.cs | 18 +- .../src/System/Xml/Dom/XmlElementList.cs | 10 +- .../src/System/Xml/Dom/XmlLoader.cs | 8 +- .../src/System/Xml/Dom/XmlName.cs | 8 +- .../src/System/Xml/Dom/XmlNode.cs | 3 +- .../src/System/Xml/Dom/XmlNodeReader.cs | 46 +- .../src/System/Xml/Dom/XmlNotation.cs | 6 +- .../src/System/Xml/Schema/Asttree.cs | 18 +- .../src/System/Xml/Schema/AutoValidator.cs | 6 +- .../src/System/Xml/Schema/BaseProcessor.cs | 13 +- .../src/System/Xml/Schema/BaseValidator.cs | 14 +- .../Xml/Schema/CompiledidEntityConstraint.cs | 12 +- .../src/System/Xml/Schema/ContentValidator.cs | 2 +- .../Xml/Schema/DataTypeImplementation.cs | 24 +- .../src/System/Xml/Schema/DtdParser.cs | 6 +- .../src/System/Xml/Schema/DtdValidator.cs | 22 +- .../src/System/Xml/Schema/FacetChecker.cs | 30 +- .../src/System/Xml/Schema/NamespaceList.cs | 8 +- .../src/System/Xml/Schema/Parser.cs | 16 +- .../src/System/Xml/Schema/ParserAsync.cs | 18 +- .../src/System/Xml/Schema/Preprocessor.cs | 57 +- .../src/System/Xml/Schema/SchemaAttDef.cs | 10 +- .../Xml/Schema/SchemaCollectionCompiler.cs | 41 +- .../Schema/SchemaCollectionpreProcessor.cs | 75 +- .../src/System/Xml/Schema/SchemaDeclBase.cs | 12 +- .../System/Xml/Schema/SchemaElementDecl.cs | 10 +- .../src/System/Xml/Schema/SchemaEntity.cs | 10 +- .../src/System/Xml/Schema/SchemaInfo.cs | 5 +- .../src/System/Xml/Schema/SchemaNames.cs | 6 +- .../Xml/Schema/SchemaNamespacemanager.cs | 10 +- .../src/System/Xml/Schema/SchemaNotation.cs | 6 +- .../System/Xml/Schema/SchemaSetCompiler.cs | 44 +- .../src/System/Xml/Schema/ValidationState.cs | 10 +- .../src/System/Xml/Schema/XdrBuilder.cs | 22 +- .../src/System/Xml/Schema/XdrValidator.cs | 18 +- .../src/System/Xml/Schema/XmlSchema.cs | 18 +- .../src/System/Xml/Schema/XmlSchemaAll.cs | 6 +- .../System/Xml/Schema/XmlSchemaAnnotated.cs | 6 +- .../System/Xml/Schema/XmlSchemaAnnotation.cs | 6 +- .../src/System/Xml/Schema/XmlSchemaAny.cs | 8 +- .../Xml/Schema/XmlSchemaAnyAttribute.cs | 8 +- .../src/System/Xml/Schema/XmlSchemaAppInfo.cs | 6 +- .../System/Xml/Schema/XmlSchemaAttribute.cs | 4 +- .../Xml/Schema/XmlSchemaAttributeGroup.cs | 6 +- .../Xml/Schema/XmlSchemaAttributeGroupref.cs | 10 +- .../src/System/Xml/Schema/XmlSchemaChoice.cs | 6 +- .../System/Xml/Schema/XmlSchemaCollection.cs | 27 +- .../Xml/Schema/XmlSchemaComplexContent.cs | 4 +- .../XmlSchemaComplexContentExtension.cs | 8 +- .../XmlSchemaComplexContentRestriction.cs | 8 +- .../src/System/Xml/Schema/XmlSchemaContent.cs | 6 +- .../Xml/Schema/XmlSchemaContentModel.cs | 4 +- .../Xml/Schema/XmlSchemaContentProcessing.cs | 4 +- .../Xml/Schema/XmlSchemaDerivationMethod.cs | 8 +- .../Xml/Schema/XmlSchemaDocumentation.cs | 10 +- .../src/System/Xml/Schema/XmlSchemaElement.cs | 6 +- .../System/Xml/Schema/XmlSchemaException.cs | 2 +- .../System/Xml/Schema/XmlSchemaExternal.cs | 8 +- .../src/System/Xml/Schema/XmlSchemaFacet.cs | 6 +- .../src/System/Xml/Schema/XmlSchemaForm.cs | 4 +- .../src/System/Xml/Schema/XmlSchemaGroup.cs | 4 +- .../System/Xml/Schema/XmlSchemaGroupBase.cs | 4 +- .../System/Xml/Schema/XmlSchemaGroupRef.cs | 6 +- .../Xml/Schema/XmlSchemaIdEntityConstraint.cs | 10 +- .../src/System/Xml/Schema/XmlSchemaImport.cs | 4 +- .../src/System/Xml/Schema/XmlSchemaInclude.cs | 4 +- .../System/Xml/Schema/XmlSchemaNotation.cs | 4 +- .../src/System/Xml/Schema/XmlSchemaObject.cs | 6 +- .../Xml/Schema/XmlSchemaObjectCollection.cs | 8 +- .../System/Xml/Schema/XmlSchemaObjectTable.cs | 8 +- .../System/Xml/Schema/XmlSchemaParticle.cs | 4 +- .../System/Xml/Schema/XmlSchemaRedefine.cs | 4 +- .../System/Xml/Schema/XmlSchemaSequence.cs | 4 +- .../src/System/Xml/Schema/XmlSchemaSet.cs | 13 +- .../Xml/Schema/XmlSchemaSimpleContent.cs | 4 +- .../Schema/XmlSchemaSimpleContentExtension.cs | 6 +- .../XmlSchemaSimpleContentRestriction.cs | 6 +- .../System/Xml/Schema/XmlSchemaSimpleType.cs | 6 +- .../Xml/Schema/XmlSchemaSimpleTypeList.cs | 6 +- .../Schema/XmlSchemaSimpleTypeRestriction.cs | 8 +- .../Xml/Schema/XmlSchemaSimpleTypeUnion.cs | 4 +- .../Xml/Schema/XmlSchemaSubstitutionGroup.cs | 6 +- .../src/System/Xml/Schema/XmlSchemaUse.cs | 4 +- .../System/Xml/Schema/XmlSchemaValidator.cs | 12 +- .../src/System/Xml/Schema/XsdDateTime.cs | 10 +- .../src/System/Xml/Schema/XsdDuration.cs | 7 +- .../src/System/Xml/Schema/XsdValidator.cs | 24 +- .../Serialization/CodeGenerationoptions.cs | 8 +- .../System/Xml/Serialization/CodeGenerator.cs | 9 +- .../Xml/Serialization/CodeIdentifiers.cs | 10 +- .../System/Xml/Serialization/Compilation.cs | 1 + .../DateTimeSerializationSection.cs | 12 +- .../Xml/Serialization/IXmlSerializable.cs | 8 +- .../Xml/Serialization/IXmlTextParser.cs | 4 +- .../System/Xml/Serialization/ImportContext.cs | 51 +- .../src/System/Xml/Serialization/Mappings.cs | 36 +- .../src/System/Xml/Serialization/Models.cs | 14 +- .../src/System/Xml/Serialization/NameTable.cs | 9 +- .../ReflectionXmlSerializationReader.cs | 4 + .../Xml/Serialization/SchemaImporter.cs | 22 +- .../Xml/Serialization/SchemaObjectWriter.cs | 41 +- .../Serialization/SoapAttributeAttribute.cs | 10 +- .../Serialization/SoapAttributeOverrides.cs | 14 +- .../Xml/Serialization/SoapElementAttribute.cs | 10 +- .../Xml/Serialization/SoapEnumAttribute.cs | 8 +- .../Xml/Serialization/SoapIgnoreAttribute.cs | 4 +- .../Xml/Serialization/SoapIncludeAttribute.cs | 2 + .../Serialization/SoapReflectionImporter.cs | 29 +- .../Xml/Serialization/SoapSchemamember.cs | 10 +- .../Xml/Serialization/SoapTypeAttribute.cs | 8 +- .../Xml/Serialization/TypeExtensions.cs | 8 +- .../src/System/Xml/Serialization/Types.cs | 31 +- .../Serialization/XmlAnyElementAttribute.cs | 2 +- .../Serialization/XmlAnyElementAttributes.cs | 10 +- .../Xml/Serialization/XmlArrayAttribute.cs | 2 +- .../Serialization/XmlArrayItemAttribute.cs | 4 +- .../Serialization/XmlArrayItemAttributes.cs | 10 +- .../Serialization/XmlAttributeAttribute.cs | 4 +- .../Serialization/XmlAttributeOverrides.cs | 16 +- .../System/Xml/Serialization/XmlAttributes.cs | 3 +- .../XmlChoiceIdentifierAttribute.cs | 2 +- .../Xml/Serialization/XmlElementAttribute.cs | 4 +- .../Xml/Serialization/XmlElementAttributes.cs | 10 +- .../System/Xml/Serialization/XmlMapping.cs | 2 +- .../Serialization/XmlReflectionImporter.cs | 77 +- .../Xml/Serialization/XmlReflectionMember.cs | 2 +- .../Xml/Serialization/XmlRootAttribute.cs | 6 +- .../Xml/Serialization/XmlSchemaExporter.cs | 47 +- .../Xml/Serialization/XmlSchemaImporter.cs | 93 +- .../XmlSchemaProviderAttribute.cs | 6 +- .../System/Xml/Serialization/XmlSchemas.cs | 42 +- .../XmlSerializationGeneratedCode.cs | 20 +- .../Serialization/XmlSerializationILGen.cs | 16 +- .../Serialization/XmlSerializationReader.cs | 70 +- .../XmlSerializationReaderILGen.cs | 68 +- .../Serialization/XmlSerializationWriter.cs | 107 +- .../XmlSerializationWriterILGen.cs | 53 +- .../System/Xml/Serialization/XmlSerializer.cs | 3 +- .../XmlSerializerAssemblyAttribute.cs | 4 +- .../Xml/Serialization/XmlSerializerFactory.cs | 26 +- .../Serialization/XmlSerializerNamespaces.cs | 18 +- .../XmlSerializerVersionAttribute.cs | 4 +- .../Xml/Serialization/XmlTextAttribute.cs | 2 +- .../Xml/Serialization/XmlTypeAttribute.cs | 2 +- .../Xml/Serialization/Xmlcustomformatter.cs | 24 +- .../src/System/Xml/Serialization/_Events.cs | 16 +- .../Xml/Serialization/indentedWriter.cs | 4 +- .../Xml/XPath/Internal/XPathMultyIterator.cs | 14 +- .../src/System/Xml/XPath/XPathException.cs | 2 +- .../src/System/Xml/XPath/XPathNavigator.cs | 2 +- .../src/System/Xml/XmlComplianceUtil.cs | 3 +- .../src/System/Xml/XmlConvert.cs | 7 +- .../src/System/Xml/XmlException.cs | 2 +- .../src/System/Xml/XmlNamespacemanager.cs | 2 +- .../src/System/Xml/XmlResolver.cs | 18 +- .../src/System/Xml/XmlSecureResolver.cs | 8 +- .../System/Xml/Xsl/IlGen/OptimizerPatterns.cs | 2 +- .../System/Xml/Xsl/IlGen/StaticDataManager.cs | 12 +- .../Xml/Xsl/IlGen/XmlILConstructAnalyzer.cs | 2 +- .../src/System/Xml/Xsl/IlGen/XmlILModule.cs | 3 +- .../src/System/Xml/Xsl/IlGen/XmlIlVisitor.cs | 3 +- .../src/System/Xml/Xsl/QIL/QilCloneVisitor.cs | 2 +- .../System/Xml/Xsl/QIL/QilReplaceVisitor.cs | 2 +- .../src/System/Xml/Xsl/QIL/QilXmlWriter.cs | 4 +- .../Xml/Xsl/Runtime/WhitespaceRuleReader.cs | 2 +- .../Xml/Xsl/Runtime/XmlAttributeCache.cs | 16 +- .../System/Xml/Xsl/Runtime/XmlQueryContext.cs | 18 +- .../src/System/Xml/Xsl/XPath/XPathBuilder.cs | 5 +- .../src/System/Xml/Xsl/XPath/XPathParser.cs | 46 +- .../System/Xml/Xsl/XPath/XPathQilFactory.cs | 3 +- .../src/System/Xml/Xsl/XPathConvert.cs | 2 +- .../System/Xml/Xsl/XmlQualifiedNameTest.cs | 2 +- .../src/System/Xml/Xsl/XmlQueryType.cs | 2 +- .../src/System/Xml/Xsl/XmlQueryTypeFactory.cs | 3 +- .../src/System/Xml/Xsl/XslException.cs | 2 +- .../Xml/Xsl/Xslt/CompilerScopeManager.cs | 3 +- .../src/System/Xml/Xsl/Xslt/Focus.cs | 3 +- .../System/Xml/Xsl/Xslt/InvokeGenerator.cs | 3 +- .../src/System/Xml/Xsl/Xslt/MatcherBuilder.cs | 3 +- .../src/System/Xml/Xsl/Xslt/QilGenerator.cs | 24 +- .../System/Xml/Xsl/Xslt/QilGeneratorEnv.cs | 5 +- .../Xml/Xsl/Xslt/XPathPatternBuilder.cs | 7 +- .../System/Xml/Xsl/Xslt/XPathPatternParser.cs | 5 +- .../src/System/Xml/Xsl/Xslt/XslAst.cs | 5 +- .../src/System/Xml/Xsl/Xslt/XslAstAnalyzer.cs | 7 +- .../src/System/Xml/Xsl/Xslt/XsltInput.cs | 2 +- .../src/System/Xml/Xsl/Xslt/XsltLoader.cs | 19 +- .../src/System/Xml/Xsl/Xslt/XsltQilFactory.cs | 3 +- .../src/System/Xml/Xsl/XsltOld/ActionFrame.cs | 16 +- .../Xml/Xsl/XsltOld/ApplyImportsAction.cs | 10 +- .../Xml/Xsl/XsltOld/ApplyTemplatesAction.cs | 12 +- .../System/Xml/Xsl/XsltOld/AttributeAction.cs | 12 +- .../Xml/Xsl/XsltOld/AttributeSetAction.cs | 12 +- .../src/System/Xml/Xsl/XsltOld/Avt.cs | 16 +- .../src/System/Xml/Xsl/XsltOld/AvtEvent.cs | 12 +- .../src/System/Xml/Xsl/XsltOld/BeginEvent.cs | 10 +- .../src/System/Xml/Xsl/XsltOld/BuilderInfo.cs | 16 +- .../Xml/Xsl/XsltOld/CallTemplateAction.cs | 10 +- .../System/Xml/Xsl/XsltOld/ChooseAction.cs | 10 +- .../System/Xml/Xsl/XsltOld/CommentAction.cs | 10 +- .../System/Xml/Xsl/XsltOld/CompiledAction.cs | 10 +- .../System/Xml/Xsl/XsltOld/ContainerAction.cs | 24 +- .../src/System/Xml/Xsl/XsltOld/CopyAction.cs | 12 +- .../Xml/Xsl/XsltOld/CopyAttributesAction.cs | 10 +- .../System/Xml/Xsl/XsltOld/CopyCodeAction.cs | 12 +- .../Xml/Xsl/XsltOld/CopyNodeSetAction.cs | 10 +- .../System/Xml/Xsl/XsltOld/CopyOfAction.cs | 12 +- .../System/Xml/Xsl/XsltOld/DocumentScope.cs | 10 +- .../System/Xml/Xsl/XsltOld/ElementAction.cs | 10 +- .../src/System/Xml/Xsl/XsltOld/EndEvent.cs | 10 +- .../src/System/Xml/Xsl/XsltOld/Event.cs | 12 +- .../System/Xml/Xsl/XsltOld/ForEachAction.cs | 12 +- .../src/System/Xml/Xsl/XsltOld/HtmlProps.cs | 14 +- .../src/System/Xml/Xsl/XsltOld/IfAction.cs | 10 +- .../src/System/Xml/Xsl/XsltOld/InputScope.cs | 12 +- .../Xml/Xsl/XsltOld/InputScopeManager.cs | 10 +- .../System/Xml/Xsl/XsltOld/MessageAction.cs | 14 +- .../System/Xml/Xsl/XsltOld/NameSpaceEvent.cs | 10 +- .../System/Xml/Xsl/XsltOld/NamespaceDecl.cs | 8 +- .../System/Xml/Xsl/XsltOld/NavigatorInput.cs | 14 +- .../System/Xml/Xsl/XsltOld/NumberAction.cs | 5 + .../src/System/Xml/Xsl/XsltOld/OutKeywords.cs | 8 +- .../src/System/Xml/Xsl/XsltOld/OutputScope.cs | 10 +- .../Xml/Xsl/XsltOld/OutputScopeManager.cs | 10 +- .../src/System/Xml/Xsl/XsltOld/PrefixQName.cs | 10 +- .../XsltOld/ProcessingInstructionAction.cs | 8 +- .../src/System/Xml/Xsl/XsltOld/Processor.cs | 26 +- .../System/Xml/Xsl/XsltOld/RecordBuilder.cs | 4 +- .../src/System/Xml/Xsl/XsltOld/RootAction.cs | 22 +- .../Xml/Xsl/XsltOld/SequentialOutput.cs | 4 +- .../src/System/Xml/Xsl/XsltOld/SortAction.cs | 15 +- .../System/Xml/Xsl/XsltOld/StateMachine.cs | 10 +- .../System/Xml/Xsl/XsltOld/StringOutput.cs | 8 +- .../src/System/Xml/Xsl/XsltOld/Stylesheet.cs | 12 +- .../System/Xml/Xsl/XsltOld/TemplateAction.cs | 16 +- .../Xml/Xsl/XsltOld/TemplateBaseAction.cs | 14 +- .../Xml/Xsl/XsltOld/TemplateLookupAction.cs | 12 +- .../System/Xml/Xsl/XsltOld/TemplateManager.cs | 12 +- .../src/System/Xml/Xsl/XsltOld/TextAction.cs | 10 +- .../src/System/Xml/Xsl/XsltOld/TextEvent.cs | 10 +- .../src/System/Xml/Xsl/XsltOld/TextOutput.cs | 12 +- .../src/System/Xml/Xsl/XsltOld/TheQuery.cs | 10 +- .../Xml/Xsl/XsltOld/UseAttributeSetsAction.cs | 12 +- .../System/Xml/Xsl/XsltOld/ValueOfAction.cs | 10 +- .../System/Xml/Xsl/XsltOld/WithParamAction.cs | 12 +- .../Xml/Xsl/XsltOld/XsltCompileContext.cs | 24 +- .../System/Xml/Xsl/XsltOld/XsltDebugger.cs | 4 +- .../src/System/Xml/Xsl/XsltOld/XsltOutput.cs | 14 +- .../Xml/Xsl/XsltOld/newinstructionaction.cs | 10 +- .../src/System/Xml/Xslt/XslTransform.cs | 16 +- .../TestData/xsltc/baseline/2-(1)cnt19.xsl | 9 + .../TestData/xsltc/baseline/bft 25.xsl | 9 + .../TestData/xsltc/baseline/bft1.txt | 1 + .../TestData/xsltc/baseline/bft1.xsl | 9 + .../TestData/xsltc/baseline/bft10.txt | 1 + .../TestData/xsltc/baseline/bft10a.xsl | 9 + .../TestData/xsltc/baseline/bft10b.xsl | 9 + .../TestData/xsltc/baseline/bft11.txt | 1 + .../TestData/xsltc/baseline/bft11a.xsl | 9 + .../TestData/xsltc/baseline/bft11b.xsl | 9 + .../TestData/xsltc/baseline/bft11c.xsl | 9 + .../TestData/xsltc/baseline/bft12.txt | 1 + .../TestData/xsltc/baseline/bft12a.xsl | 9 + .../TestData/xsltc/baseline/bft12b.xsl | 9 + .../TestData/xsltc/baseline/bft12c.xsl | 9 + .../TestData/xsltc/baseline/bft12d.xsl | 9 + .../TestData/xsltc/baseline/bft12e.xsl | 9 + .../TestData/xsltc/baseline/bft12f.xsl | 9 + .../TestData/xsltc/baseline/bft12g.xsl | 9 + .../TestData/xsltc/baseline/bft12h.xsl | 9 + .../TestData/xsltc/baseline/bft12i.xsl | 9 + .../TestData/xsltc/baseline/bft12j.xsl | 9 + .../TestData/xsltc/baseline/bft12k.xsl | 9 + .../TestData/xsltc/baseline/bft12l.xsl | 9 + .../TestData/xsltc/baseline/bft12m.xsl | 9 + .../TestData/xsltc/baseline/bft12n.xsl | 9 + .../TestData/xsltc/baseline/bft12o.xsl | 9 + .../TestData/xsltc/baseline/bft12p.xsl | 9 + .../TestData/xsltc/baseline/bft12q.xsl | 9 + .../TestData/xsltc/baseline/bft12r.xsl | 9 + .../TestData/xsltc/baseline/bft12s.xsl | 9 + .../TestData/xsltc/baseline/bft12t.xsl | 9 + .../TestData/xsltc/baseline/bft12u.xsl | 9 + .../TestData/xsltc/baseline/bft12v.xsl | 9 + .../TestData/xsltc/baseline/bft12w.xsl | 9 + .../TestData/xsltc/baseline/bft12x.xsl | 9 + .../TestData/xsltc/baseline/bft12y.xsl | 9 + .../TestData/xsltc/baseline/bft12z.xsl | 9 + .../TestData/xsltc/baseline/bft13.txt | 1 + .../TestData/xsltc/baseline/bft13.xsl | 9 + .../TestData/xsltc/baseline/bft14.txt | 1 + .../TestData/xsltc/baseline/bft14a.xsl | 9 + .../TestData/xsltc/baseline/bft15.txt | 6 + .../TestData/xsltc/baseline/bft15a.xsl | 11 + .../TestData/xsltc/baseline/bft15b.xsl | 11 + .../TestData/xsltc/baseline/bft16.txt | 5 + .../TestData/xsltc/baseline/bft16.xsl | 9 + .../TestData/xsltc/baseline/bft16.xslt | 9 + .../TestData/xsltc/baseline/bft17.txt | 1 + .../TestData/xsltc/baseline/bft18.txt | 6 + .../TestData/xsltc/baseline/bft18a.xsl | 11 + .../TestData/xsltc/baseline/bft18b.xsl | 11 + .../TestData/xsltc/baseline/bft19.txt | 1 + .../TestData/xsltc/baseline/bft19.xsl | 13 + .../TestData/xsltc/baseline/bft19a.xsl | 11 + .../TestData/xsltc/baseline/bft2.txt | 1 + .../TestData/xsltc/baseline/bft2.xsl | 9 + .../TestData/xsltc/baseline/bft20.txt | 1 + .../TestData/xsltc/baseline/bft20.xsl | 13 + .../TestData/xsltc/baseline/bft20a.xsl | 11 + .../TestData/xsltc/baseline/bft21.txt | 4 + .../TestData/xsltc/baseline/bft21.xsl | 18 + .../TestData/xsltc/baseline/bft21a.xml | 8 + .../TestData/xsltc/baseline/bft22.txt | 1 + .../TestData/xsltc/baseline/bft22.xsl | 9 + .../TestData/xsltc/baseline/bft23.txt | 1 + .../TestData/xsltc/baseline/bft23.xsl | 9 + .../TestData/xsltc/baseline/bft24.txt | 6 + .../TestData/xsltc/baseline/bft24a.xsl | 11 + .../TestData/xsltc/baseline/bft24b.xsl | 11 + .../TestData/xsltc/baseline/bft25.txt | 1 + .../TestData/xsltc/baseline/bft26.txt | 1 + .../TestData/xsltc/baseline/bft26.xsl | 9 + .../TestData/xsltc/baseline/bft27.txt | 5 + .../TestData/xsltc/baseline/bft28.txt | 5 + .../TestData/xsltc/baseline/bft29.txt | 30 + .../TestData/xsltc/baseline/bft3.txt | 1 + .../TestData/xsltc/baseline/bft3.xsl | 9 + .../TestData/xsltc/baseline/bft30.txt | 30 + .../TestData/xsltc/baseline/bft31.txt | 1 + .../TestData/xsltc/baseline/bft31.xsl | 9 + .../TestData/xsltc/baseline/bft32.txt | 5 + .../TestData/xsltc/baseline/bft33.txt | 1 + .../TestData/xsltc/baseline/bft34.txt | 5 + .../TestData/xsltc/baseline/bft35.txt | 5 + .../TestData/xsltc/baseline/bft36.txt | 5 + .../TestData/xsltc/baseline/bft37.txt | 5 + .../TestData/xsltc/baseline/bft38.txt | 5 + .../TestData/xsltc/baseline/bft4.xsl | 9 + .../TestData/xsltc/baseline/bft5.txt | 5 + .../TestData/xsltc/baseline/bft6.txt | 5 + .../TestData/xsltc/baseline/bft7.txt | 5 + .../TestData/xsltc/baseline/bft8.txt | 5 + .../TestData/xsltc/baseline/bft9.txt | 5 + .../TestData/xsltc/baseline/cct1.txt | 2 + .../TestData/xsltc/baseline/cnt1.txt | 1 + .../TestData/xsltc/baseline/cnt1.xsl | 9 + .../TestData/xsltc/baseline/cnt10.txt | 2 + .../TestData/xsltc/baseline/cnt10a.xsl | 9 + .../TestData/xsltc/baseline/cnt10b.xsl | 10 + .../TestData/xsltc/baseline/cnt11.txt | 1 + .../TestData/xsltc/baseline/cnt11a.xsl | 9 + .../TestData/xsltc/baseline/cnt11b.xsl | 10 + .../TestData/xsltc/baseline/cnt12.txt | 1 + .../TestData/xsltc/baseline/cnt12a.xsl | 9 + .../TestData/xsltc/baseline/cnt12b.xsl | 10 + .../TestData/xsltc/baseline/cnt13.txt | 5 + .../TestData/xsltc/baseline/cnt13.xsl | 9 + .../TestData/xsltc/baseline/cnt14.txt | 1 + .../TestData/xsltc/baseline/cnt14.xsl | 9 + .../TestData/xsltc/baseline/cnt14b.xsl | 9 + .../TestData/xsltc/baseline/cnt15.txt | 5 + .../TestData/xsltc/baseline/cnt15a.xsl | 9 + .../TestData/xsltc/baseline/cnt15b.xsl | 9 + .../TestData/xsltc/baseline/cnt16.txt | 1 + .../TestData/xsltc/baseline/cnt17.txt | 1 + .../TestData/xsltc/baseline/cnt18.txt | 5 + .../TestData/xsltc/baseline/cnt18.xsl | 9 + .../TestData/xsltc/baseline/cnt18.xslt | 9 + .../TestData/xsltc/baseline/cnt19.txt | 1 + .../TestData/xsltc/baseline/cnt2.txt | 1 + .../TestData/xsltc/baseline/cnt2.xsl | 9 + .../TestData/xsltc/baseline/cnt20.txt | 6 + .../TestData/xsltc/baseline/cnt20.xsl | 9 + .../TestData/xsltc/baseline/cnt21.txt | 1 + .../TestData/xsltc/baseline/cnt21.xsl | 9 + .../TestData/xsltc/baseline/cnt22.txt | 1 + .../TestData/xsltc/baseline/cnt22.xsl | 9 + .../TestData/xsltc/baseline/cnt23.txt | 1 + .../TestData/xsltc/baseline/cnt23.xsl | 9 + .../TestData/xsltc/baseline/cnt24.txt | 5 + .../TestData/xsltc/baseline/cnt25.txt | 1 + .../TestData/xsltc/baseline/cnt25a.xsl | 9 + .../TestData/xsltc/baseline/cnt25b.xsl | 10 + .../TestData/xsltc/baseline/cnt26.txt | 1 + .../TestData/xsltc/baseline/cnt26a.xsl | 9 + .../TestData/xsltc/baseline/cnt26b.xsl | 10 + .../TestData/xsltc/baseline/cnt27.txt | 1 + .../TestData/xsltc/baseline/cnt27a.xsl | 9 + .../TestData/xsltc/baseline/cnt27b.xsl | 10 + .../TestData/xsltc/baseline/cnt28.txt | 1 + .../TestData/xsltc/baseline/cnt28a.xsl | 9 + .../TestData/xsltc/baseline/cnt28b.xsl | 10 + .../TestData/xsltc/baseline/cnt29.txt | 1 + .../TestData/xsltc/baseline/cnt29a.xsl | 9 + .../TestData/xsltc/baseline/cnt29b.xsl | 10 + .../TestData/xsltc/baseline/cnt3.txt | 5 + .../TestData/xsltc/baseline/cnt3.xsl | 9 + .../TestData/xsltc/baseline/cnt4.txt | 1 + .../TestData/xsltc/baseline/cnt4.xsl | 9 + .../TestData/xsltc/baseline/cnt5.txt | 1 + .../TestData/xsltc/baseline/cnt5.xsl | 9 + .../TestData/xsltc/baseline/cnt6.txt | 1 + .../TestData/xsltc/baseline/cnt6.xsl | 9 + .../TestData/xsltc/baseline/cnt7.txt | 1 + .../TestData/xsltc/baseline/cnt7.xsl | 9 + .../TestData/xsltc/baseline/cnt8.txt | 1 + .../TestData/xsltc/baseline/cnt8a.xsl | 9 + .../TestData/xsltc/baseline/cnt8b.xsl | 10 + .../TestData/xsltc/baseline/cnt9.txt | 1 + .../TestData/xsltc/baseline/cnt9a.xsl | 9 + .../TestData/xsltc/baseline/cnt9b.xsl | 10 + .../TestData/xsltc/baseline/dft1.txt | 1 + .../TestData/xsltc/baseline/dft1.xsl | 9 + .../TestData/xsltc/baseline/dft10.txt | 1 + .../TestData/xsltc/baseline/dft10.xsl | 9 + .../TestData/xsltc/baseline/dft11.txt | 1 + .../TestData/xsltc/baseline/dft11.xsl | 9 + .../TestData/xsltc/baseline/dft12.txt | 1 + .../TestData/xsltc/baseline/dft12.xsl | 9 + .../TestData/xsltc/baseline/dft13.txt | 1 + .../TestData/xsltc/baseline/dft13.xsl | 9 + .../TestData/xsltc/baseline/dft14.txt | 1 + .../TestData/xsltc/baseline/dft14.xsl | 9 + .../TestData/xsltc/baseline/dft15.txt | 5 + .../TestData/xsltc/baseline/dft15.xsl | 9 + .../TestData/xsltc/baseline/dft16.txt | 5 + .../TestData/xsltc/baseline/dft16.xsl | 9 + .../TestData/xsltc/baseline/dft17.txt | 5 + .../TestData/xsltc/baseline/dft17.xsl | 9 + .../TestData/xsltc/baseline/dft18.txt | 5 + .../TestData/xsltc/baseline/dft18.xsl | 9 + .../TestData/xsltc/baseline/dft19.txt | 5 + .../TestData/xsltc/baseline/dft19.xsl | 9 + .../TestData/xsltc/baseline/dft2.txt | 1 + .../TestData/xsltc/baseline/dft2.xsl | 9 + .../TestData/xsltc/baseline/dft20.txt | 5 + .../TestData/xsltc/baseline/dft20.xsl | 9 + .../TestData/xsltc/baseline/dft21.txt | 5 + .../TestData/xsltc/baseline/dft21.xsl | 9 + .../TestData/xsltc/baseline/dft22.txt | 1 + .../TestData/xsltc/baseline/dft22.xsl | 9 + .../TestData/xsltc/baseline/dft23.txt | 1 + .../TestData/xsltc/baseline/dft23.xsl | 9 + .../TestData/xsltc/baseline/dft3.txt | 5 + .../TestData/xsltc/baseline/dft3.xsl | 9 + .../TestData/xsltc/baseline/dft4.txt | 5 + .../TestData/xsltc/baseline/dft4.xsl | 9 + .../TestData/xsltc/baseline/dft5.txt | 5 + .../TestData/xsltc/baseline/dft5.xsl | 9 + .../TestData/xsltc/baseline/dft6.txt | 1 + .../TestData/xsltc/baseline/dft6.xsl | 9 + .../TestData/xsltc/baseline/dft7.txt | 5 + .../TestData/xsltc/baseline/dft7.xsl | 9 + .../TestData/xsltc/baseline/dft8.txt | 1 + .../TestData/xsltc/baseline/dft8.xsl | 9 + .../TestData/xsltc/baseline/dft9.txt | 1 + .../TestData/xsltc/baseline/dft9.xsl | 9 + .../TestData/xsltc/baseline/fft10.txt | 5 + .../TestData/xsltc/baseline/fft10.xsl | 9 + .../TestData/xsltc/baseline/fft11.txt | 1 + .../TestData/xsltc/baseline/fft11.xsl | 9 + .../TestData/xsltc/baseline/fft12.txt | 5 + .../TestData/xsltc/baseline/fft12.xsl | 9 + .../TestData/xsltc/baseline/fft13.txt | 1 + .../TestData/xsltc/baseline/fft13.xsl | 9 + .../TestData/xsltc/baseline/fft14.txt | 5 + .../TestData/xsltc/baseline/fft14.xsl | 9 + .../TestData/xsltc/baseline/fft15.txt | 5 + .../TestData/xsltc/baseline/fft15.xsl | 9 + .../TestData/xsltc/baseline/fft16.txt | 1 + .../TestData/xsltc/baseline/fft16.xsl | 9 + .../TestData/xsltc/baseline/fft17.txt | 1 + .../TestData/xsltc/baseline/fft17.xsl | 9 + .../TestData/xsltc/baseline/fft18.txt | 1 + .../TestData/xsltc/baseline/fft18.xsl | 9 + .../TestData/xsltc/baseline/fft19.txt | 5 + .../TestData/xsltc/baseline/fft2.txt | 1 + .../TestData/xsltc/baseline/fft2.xsl | 9 + .../TestData/xsltc/baseline/fft20.txt | 5 + .../TestData/xsltc/baseline/fft21.txt | 5 + .../TestData/xsltc/baseline/fft3.txt | 1 + .../TestData/xsltc/baseline/fft3.xsl | 9 + .../TestData/xsltc/baseline/fft4.txt | 1 + .../TestData/xsltc/baseline/fft4.xsl | 9 + .../TestData/xsltc/baseline/fft5.txt | 7 + .../TestData/xsltc/baseline/fft6.txt | 1 + .../TestData/xsltc/baseline/fft6.xsl | 9 + .../TestData/xsltc/baseline/fft7.txt | 1 + .../TestData/xsltc/baseline/fft7a.xsl | 9 + .../TestData/xsltc/baseline/fft7b.xsl | 9 + .../TestData/xsltc/baseline/fft8.txt | 1 + .../TestData/xsltc/baseline/fft8a.xsl | 9 + .../TestData/xsltc/baseline/fft8b.xsl | 9 + .../TestData/xsltc/baseline/fft8c.xsl | 9 + .../TestData/xsltc/baseline/fft8d.xsl | 9 + .../TestData/xsltc/baseline/fft9.txt | 5 + .../TestData/xsltc/baseline/fft9.xsl | 9 + .../TestData/xsltc/baseline/help.txt | 30 + .../TestData/xsltc/baseline/identity.xsl | 7 + .../TestData/xsltc/baseline/infft10.txt | 1 + .../TestData/xsltc/baseline/infft10b.txt | 1 + .../TestData/xsltc/baseline/infft10c.txt | 1 + .../TestData/xsltc/baseline/infft11.txt | 1 + .../TestData/xsltc/baseline/infft11a.txt | 1 + .../TestData/xsltc/baseline/infft11b.txt | 1 + .../TestData/xsltc/baseline/infft12.txt | 1 + .../TestData/xsltc/baseline/infft12b.txt | 1 + .../TestData/xsltc/baseline/infft12c.txt | 1 + .../TestData/xsltc/baseline/infft13.txt | 1 + .../TestData/xsltc/baseline/infft13a.txt | 1 + .../TestData/xsltc/baseline/infft13b.txt | 1 + .../TestData/xsltc/baseline/infft14.txt | 1 + .../TestData/xsltc/baseline/infft14b.txt | 1 + .../TestData/xsltc/baseline/infft14c.txt | 1 + .../TestData/xsltc/baseline/infft15.txt | 1 + .../TestData/xsltc/baseline/infft15b.txt | 1 + .../TestData/xsltc/baseline/infft15c.txt | 1 + .../TestData/xsltc/baseline/infft16---.txt | Bin 0 -> 20 bytes .../TestData/xsltc/baseline/infft17.txt | 3 + .../TestData/xsltc/baseline/infft18.txt | 1 + .../TestData/xsltc/baseline/infft2.txt | Bin 0 -> 18 bytes .../TestData/xsltc/baseline/infft3.txt | 1 + .../TestData/xsltc/baseline/infft4.txt | 1 + .../TestData/xsltc/baseline/infft5.txt | 1 + .../TestData/xsltc/baseline/infft6.txt | 1 + .../TestData/xsltc/baseline/infft7a.txt | 1 + .../TestData/xsltc/baseline/infft7b.txt | 1 + .../TestData/xsltc/baseline/infft8a.txt | 1 + .../TestData/xsltc/baseline/infft8b.txt | 1 + .../TestData/xsltc/baseline/infft8c.txt | 1 + .../TestData/xsltc/baseline/infft9.txt | 1 + .../TestData/xsltc/baseline/mail.xml | 4 + .../TestData/xsltc/baseline/multith.txt | 1 + .../TestData/xsltc/baseline/ns1..cnt17.xsl | 9 + .../TestData/xsltc/baseline/ns1.ns2.cnt16.xsl | 9 + .../TestData/xsltc/baseline/oft1.txt | 1 + .../TestData/xsltc/baseline/oft1.xsl | 9 + .../TestData/xsltc/baseline/oft10.txt | 1 + .../TestData/xsltc/baseline/oft10.xsl | 9 + .../TestData/xsltc/baseline/oft11.txt | 5 + .../TestData/xsltc/baseline/oft11.xsl | 9 + .../TestData/xsltc/baseline/oft12.txt | 1 + .../TestData/xsltc/baseline/oft12.xsl | 9 + .../TestData/xsltc/baseline/oft13.txt | 1 + .../TestData/xsltc/baseline/oft13.xsl | 9 + .../TestData/xsltc/baseline/oft14.txt | 1 + .../TestData/xsltc/baseline/oft14.xsl | 9 + .../TestData/xsltc/baseline/oft15.txt | 1 + .../TestData/xsltc/baseline/oft15.xsl | 9 + .../TestData/xsltc/baseline/oft16.txt | 1 + .../TestData/xsltc/baseline/oft16.xsl | 9 + .../TestData/xsltc/baseline/oft17.txt | 1 + .../TestData/xsltc/baseline/oft17.xsl | 9 + .../TestData/xsltc/baseline/oft18.txt | 5 + .../TestData/xsltc/baseline/oft18.xsl | 9 + .../TestData/xsltc/baseline/oft19.txt | 5 + .../TestData/xsltc/baseline/oft19.xsl | 9 + .../TestData/xsltc/baseline/oft2.txt | 5 + .../TestData/xsltc/baseline/oft2.xsl | 9 + .../TestData/xsltc/baseline/oft20.txt | 5 + .../TestData/xsltc/baseline/oft20.xsl | 9 + .../TestData/xsltc/baseline/oft21.txt | 5 + .../TestData/xsltc/baseline/oft21.xsl | 9 + .../TestData/xsltc/baseline/oft22.txt | 1 + .../TestData/xsltc/baseline/oft22.xsl | 9 + .../TestData/xsltc/baseline/oft23.txt | 1 + .../TestData/xsltc/baseline/oft23.xsl | 9 + .../TestData/xsltc/baseline/oft25.txt | 1 + .../TestData/xsltc/baseline/oft25.xsl | 9 + .../TestData/xsltc/baseline/oft27.txt | 1 + .../TestData/xsltc/baseline/oft27.xsl | 9 + .../TestData/xsltc/baseline/oft28.txt | 1 + .../TestData/xsltc/baseline/oft28.xsl | 9 + .../TestData/xsltc/baseline/oft29.txt | 5 + .../TestData/xsltc/baseline/oft29.xsl | 9 + .../TestData/xsltc/baseline/oft3.txt | 1 + .../TestData/xsltc/baseline/oft3.xsl | 9 + .../TestData/xsltc/baseline/oft30.txt | 5 + .../TestData/xsltc/baseline/oft30.xsl | 9 + .../TestData/xsltc/baseline/oft31.txt | 5 + .../TestData/xsltc/baseline/oft31.xsl | 9 + .../TestData/xsltc/baseline/oft4.txt | 1 + .../TestData/xsltc/baseline/oft4a.xsl | 9 + .../TestData/xsltc/baseline/oft4b.xsl | 10 + .../TestData/xsltc/baseline/oft5.txt | 1 + .../TestData/xsltc/baseline/oft5a.xsl | 9 + .../TestData/xsltc/baseline/oft5b.xsl | 10 + .../TestData/xsltc/baseline/oft6.txt | 1 + .../TestData/xsltc/baseline/oft6a.xsl | 9 + .../TestData/xsltc/baseline/oft6b.xsl | 10 + .../TestData/xsltc/baseline/oft7.txt | 1 + .../TestData/xsltc/baseline/oft7.xsl | 9 + .../TestData/xsltc/baseline/oft8.txt | 1 + .../TestData/xsltc/baseline/oft8.xsl | 9 + .../TestData/xsltc/baseline/oft9.txt | 1 + .../TestData/xsltc/baseline/oft9.xsl | 9 + .../TestData/xsltc/baseline/pft1.txt | 1 + .../TestData/xsltc/baseline/pft1.xsl | 9 + .../TestData/xsltc/baseline/pft10.txt | 1 + .../TestData/xsltc/baseline/pft10.xsl | 9 + .../TestData/xsltc/baseline/pft11.txt | 5 + .../TestData/xsltc/baseline/pft11.xsl | 9 + .../TestData/xsltc/baseline/pft12.txt | 5 + .../TestData/xsltc/baseline/pft12.xsl | 9 + .../TestData/xsltc/baseline/pft13.txt | 5 + .../TestData/xsltc/baseline/pft13.xsl | 9 + .../TestData/xsltc/baseline/pft14.txt | 5 + .../TestData/xsltc/baseline/pft14.xsl | 9 + .../TestData/xsltc/baseline/pft15.txt | 5 + .../TestData/xsltc/baseline/pft15.xsl | 9 + .../TestData/xsltc/baseline/pft16.txt | 5 + .../TestData/xsltc/baseline/pft16.xsl | 9 + .../TestData/xsltc/baseline/pft17.txt | 1 + .../TestData/xsltc/baseline/pft17.xsl | 9 + .../TestData/xsltc/baseline/pft18.txt | 1 + .../TestData/xsltc/baseline/pft18.xsl | 9 + .../TestData/xsltc/baseline/pft19.txt | 1 + .../TestData/xsltc/baseline/pft19.xsl | 9 + .../TestData/xsltc/baseline/pft2.txt | 5 + .../TestData/xsltc/baseline/pft2.xsl | 9 + .../TestData/xsltc/baseline/pft20.txt | 1 + .../TestData/xsltc/baseline/pft20.xsl | 9 + .../TestData/xsltc/baseline/pft3.txt | 1 + .../TestData/xsltc/baseline/pft3.xsl | 9 + .../TestData/xsltc/baseline/pft4.txt | 5 + .../TestData/xsltc/baseline/pft4.xsl | 9 + .../TestData/xsltc/baseline/pft7.txt | 1 + .../TestData/xsltc/baseline/pft7.xsl | 9 + .../TestData/xsltc/baseline/pft8.dll | Bin 4096 -> 0 bytes .../TestData/xsltc/baseline/pft8.txt | 1 + .../TestData/xsltc/baseline/pft8.xsl | 9 + .../TestData/xsltc/baseline/pft9.txt | 1 + .../TestData/xsltc/baseline/pft9.xsl | 9 + .../TestData/xsltc/baseline/sft1.txt | 3 + .../TestData/xsltc/baseline/sft1.xml | 4 + .../TestData/xsltc/baseline/sft1.xsl | 13 + .../TestData/xsltc/baseline/sft10.txt | 2 + .../TestData/xsltc/baseline/sft10.xsl | 21 + .../TestData/xsltc/baseline/sft11.txt | 1 + .../TestData/xsltc/baseline/sft11.xsl | 7 + .../TestData/xsltc/baseline/sft13.txt | 1 + .../TestData/xsltc/baseline/sft13.xsl | 7 + .../TestData/xsltc/baseline/sft14.txt | 5 + .../TestData/xsltc/baseline/sft14.xsl | 9 + .../TestData/xsltc/baseline/sft15.txt | 5 + .../TestData/xsltc/baseline/sft15.xsl | 9 + .../TestData/xsltc/baseline/sft2.txt | 5 + .../TestData/xsltc/baseline/sft2.xsl | 13 + .../TestData/xsltc/baseline/sft27.txt | 3 + .../TestData/xsltc/baseline/sft27.xsl | 3 + .../TestData/xsltc/baseline/sft27a.xsl | 13 + .../TestData/xsltc/baseline/sft28.txt | 5 + .../TestData/xsltc/baseline/sft28.xsl | 3 + .../TestData/xsltc/baseline/sft28a.xsl | 13 + .../TestData/xsltc/baseline/sft29.txt | 2 + .../TestData/xsltc/baseline/sft29.xsl | 3 + .../TestData/xsltc/baseline/sft29a.xsl | 21 + .../TestData/xsltc/baseline/sft3.txt | 2 + .../TestData/xsltc/baseline/sft3.xsl | 21 + .../TestData/xsltc/baseline/sft30.txt | 5 + .../TestData/xsltc/baseline/sft30.xsl | 3 + .../TestData/xsltc/baseline/sft30a.xsl | 21 + .../TestData/xsltc/baseline/sft31.txt | 1 + .../TestData/xsltc/baseline/sft31.xsl | 3 + .../TestData/xsltc/baseline/sft31a.xsl | 7 + .../TestData/xsltc/baseline/sft32.txt | 5 + .../TestData/xsltc/baseline/sft32.xsl | 3 + .../TestData/xsltc/baseline/sft32a.xsl | 7 + .../TestData/xsltc/baseline/sft33.txt | 3 + .../TestData/xsltc/baseline/sft33.xsl | 3 + .../TestData/xsltc/baseline/sft33a.xsl | 13 + .../TestData/xsltc/baseline/sft34.txt | 5 + .../TestData/xsltc/baseline/sft34.xsl | 3 + .../TestData/xsltc/baseline/sft34a.xsl | 13 + .../TestData/xsltc/baseline/sft35.txt | 2 + .../TestData/xsltc/baseline/sft35.xsl | 3 + .../TestData/xsltc/baseline/sft35a.xsl | 21 + .../TestData/xsltc/baseline/sft36.dll | Bin 5120 -> 0 bytes .../TestData/xsltc/baseline/sft36.txt | 5 + .../TestData/xsltc/baseline/sft36.xsl | 3 + .../TestData/xsltc/baseline/sft36a.xsl | 21 + .../TestData/xsltc/baseline/sft37.txt | 1 + .../TestData/xsltc/baseline/sft37.xsl | 3 + .../TestData/xsltc/baseline/sft37a.xsl | 7 + .../TestData/xsltc/baseline/sft38.txt | 5 + .../TestData/xsltc/baseline/sft38.xsl | 3 + .../TestData/xsltc/baseline/sft38a.xsl | 7 + .../TestData/xsltc/baseline/sft4.txt | 5 + .../TestData/xsltc/baseline/sft4.xsl | 21 + .../TestData/xsltc/baseline/sft41.txt | 5 + .../TestData/xsltc/baseline/sft41.xsl | 9 + .../TestData/xsltc/baseline/sft42.txt | 5 + .../TestData/xsltc/baseline/sft42.xsl | 9 + .../TestData/xsltc/baseline/sft43.txt | 5 + .../TestData/xsltc/baseline/sft43.xsl | 9 + .../TestData/xsltc/baseline/sft44.txt | 5 + .../TestData/xsltc/baseline/sft44.xsl | 9 + .../TestData/xsltc/baseline/sft45.txt | 5 + .../TestData/xsltc/baseline/sft45.xsl | 9 + .../TestData/xsltc/baseline/sft46.txt | 5 + .../TestData/xsltc/baseline/sft46.xsl | 9 + .../TestData/xsltc/baseline/sft47.txt | 5 + .../TestData/xsltc/baseline/sft47.xsl | 9 + .../TestData/xsltc/baseline/sft48.txt | 5 + .../TestData/xsltc/baseline/sft48.xsl | 9 + .../TestData/xsltc/baseline/sft49.txt | 5 + .../TestData/xsltc/baseline/sft49.xsl | 9 + .../TestData/xsltc/baseline/sft5.txt | 1 + .../TestData/xsltc/baseline/sft5.xsl | 7 + .../TestData/xsltc/baseline/sft50.txt | 5 + .../TestData/xsltc/baseline/sft50.xsl | 9 + .../TestData/xsltc/baseline/sft6.txt | 5 + .../TestData/xsltc/baseline/sft6.xsl | 7 + .../TestData/xsltc/baseline/sft7.txt | 5 + .../TestData/xsltc/baseline/sft7.xsl | 9 + .../TestData/xsltc/baseline/sft8.txt | 1 + .../TestData/xsltc/baseline/sft8.xsl | 9 + .../TestData/xsltc/baseline/sft9.txt | 3 + .../TestData/xsltc/baseline/sft9.xsl | 13 + .../xsltc/precompiled/Scripting28.xsl | Bin 0 -> 5996 bytes .../TestData/xsltc/precompiled/sft1.xml | 4 + .../XsltCompiler/ApiTests/XsltcApiTest.cs | 52 + .../XsltcTestBasicFunctionality.cs | 45 + .../CommonScenarios/XsltcTestCaseBase.cs | 347 ++ .../CommonScenarios/XsltcTestFile.cs | 76 + .../CommonScenarios/XsltcTestPlatform.cs | 103 + .../CommonScenarios/XsltcTestSettings.cs | 70 + .../tests/Xslt/XsltCompiler/Identity.xslt | 11 + .../Xslt/XsltCompiler/IdentityTransform.xslt | 11 + .../Xslt/XsltCompiler/TestStylesheet.xslt | 13 + .../tests/Xslt/XsltCompiler/XsltCommon.cs | 674 ++++ .../XsltCompiler/XsltCompiler.Tests.csproj | 35 + .../tests/Xslt/XsltCompiler/XsltcModule.cs | 44 + .../Context/Virtual/VirtualMethodBase.cs | 26 +- ...alPropertyBase.FuncPropertyAccessorBase.cs | 4 +- .../VirtualPropertyBase.PropertyGetterBase.cs | 4 +- .../VirtualPropertyBase.PropertySetterBase.cs | 8 +- .../Context/Virtual/VirtualPropertyBase.cs | 34 +- .../System.Reflection.Emit.ILGeneration.sln | 169 +- .../System.Reflection.Emit.ILGeneration.cs | 2 +- .../tests/ILGenerator/Emit5Tests.cs | 305 -- ....Reflection.Emit.ILGeneration.Tests.csproj | 1 - .../ModuleBuilder/ModuleBuilderDefineType.cs | 2 - .../src/System.Reflection.Metadata.csproj | 1 + .../MemoryBlocks/AbstractMemoryBlock.cs | 4 +- .../MemoryBlocks/ByteArrayMemoryBlock.cs | 2 +- .../MemoryBlocks/NativeHeapMemoryBlock.cs | 2 +- .../Internal/Utilities/BitArithmetic.cs | 4 +- .../Internal/Utilities/BlobUtilities.cs | 2 +- .../Internal/Utilities/EmptyArray.cs | 12 + .../ReadOnlyUnmanagedMemoryStream.cs | 2 +- .../Reflection/Metadata/Internal/BlobHeap.cs | 2 +- .../Metadata/MetadataReader.WinMD.cs | 10 +- .../Metadata/MetadataStringDecoder.cs | 2 +- .../PortableExecutable/PEBuilder.cs | 17 +- .../PEReader.EmbeddedPortablePdb.cs | 2 +- .../Reflection/PortableExecutable/PEReader.cs | 4 +- .../src/README.md | 40 - ...stem.Reflection.MetadataLoadContext.csproj | 8 +- .../src/System/Reflection/DefaultBinder.cs | 2 +- .../TypeLoading/General/AssemblyNameData.cs | 3 - .../Reflection/TypeLoading/Types/RoType.cs | 2 +- .../System.Reflection/System.Reflection.sln | 42 - .../tests/AssemblyNameTests.cs | 3 +- .../System.Reflection.InvokeEmit.Tests.csproj | 22 - .../InvokeEmit/runtimeconfig.template.json | 5 - ....Reflection.InvokeInterpreted.Tests.csproj | 22 - .../runtimeconfig.template.json | 5 - .../System.Reflection/tests/default.rd.xml | 4 - .../Runtime/Caching/CacheMemoryMonitor.cs | 2 +- .../src/System/Runtime/Caching/MemoryCache.cs | 8 +- .../tests/ILLink.Descriptors.xml | 3 - .../tests/System/AppDomainTests.cs | 2 + .../System/Environment.GetCommandLineArgs.cs | 33 - .../tests/System/Math.cs | 140 +- .../tests/System/MathF.cs | 82 - .../tests/CheckArchitectureTests.cs | 4 - .../Analyzers/CustomTypeMarshallerAnalyzer.cs | 46 +- .../Analyzers/CustomTypeMarshallerFixer.cs | 44 +- .../PInvokeStubCodeGenerator.cs | 14 +- .../GeneratedStatements.cs | 15 +- .../ManualTypeMarshallingHelper.V1.cs | 227 -- .../ManualTypeMarshallingHelper.cs | 303 +- .../Marshalling/ArrayMarshaller.cs | 2 +- ...ributedMarshallingModelGeneratorFactory.cs | 148 +- .../CustomNativeTypeMarshallingGenerator.cs | 16 +- .../Marshalling/DelegateMarshaller.cs | 2 +- .../ICustomNativeTypeMarshallingStrategy.cs | 294 +- .../ICustomTypeMarshallingStrategy.cs | 135 - .../Marshalling/MarshallerHelpers.cs | 2 +- .../MarshallingGeneratorExtensions.cs | 2 +- .../MarshallingAttributeInfo.cs | 75 +- .../Resources/Strings.resx | 14 +- .../Resources/xlf/Strings.cs.xlf | 20 - .../Resources/xlf/Strings.de.xlf | 20 - .../Resources/xlf/Strings.es.xlf | 20 - .../Resources/xlf/Strings.fr.xlf | 20 - .../Resources/xlf/Strings.it.xlf | 20 - .../Resources/xlf/Strings.ja.xlf | 20 - .../Resources/xlf/Strings.ko.xlf | 20 - .../Resources/xlf/Strings.pl.xlf | 20 - .../Resources/xlf/Strings.pt-BR.xlf | 20 - .../Resources/xlf/Strings.ru.xlf | 20 - .../Resources/xlf/Strings.tr.xlf | 20 - .../Resources/xlf/Strings.zh-Hans.xlf | 20 - .../Resources/xlf/Strings.zh-Hant.xlf | 20 - .../StubCodeContext.cs | 19 +- .../SyntaxExtensions.cs | 11 +- .../TypeNames.cs | 3 +- .../ref/System.Runtime.InteropServices.cs | 11 +- .../CustomTypeMarshallersAttributeBase.cs | 21 - .../ManagedToUnmanagedMarshallersAttribute.cs | 32 - .../ArrayTests.cs | 8 +- .../CollectionTests.cs | 10 +- .../CustomMarshallingTests.V1.cs | 157 - .../CustomMarshallingTests.cs | 45 +- .../LibraryImportGenerator.Tests/SpanTests.cs | 10 +- .../CodeSnippets.cs | 81 - .../CompileFails.cs | 8 +- .../Compiles.cs | 27 +- .../Runtime/InteropServices/NFloatTests.cs | 650 --- .../tests/TestAssets/NativeExports/Arrays.cs | 4 +- .../NativeExports/CustomMarshalling.cs | 16 +- .../TestAssets/SharedTypes/NonBlittable.V1.cs | 283 -- .../TestAssets/SharedTypes/NonBlittable.cs | 292 +- .../tests/AssemblyLoadContextTest.cs | 2 + .../ref/System.Runtime.Numerics.cs | 26 +- .../src/System/Numerics/BigInteger.cs | 49 + .../Numerics/BigIntegerCalculator.DivRem.cs | 6 +- .../Numerics/BigIntegerCalculator.PowMod.cs | 16 +- .../src/System/Numerics/Complex.cs | 41 + .../Formatters/Binary/BinaryObjectReader.cs | 14 +- .../Formatters/Binary/BinaryObjectWriter.cs | 5 +- .../Formatters/Binary/BinaryParser.cs | 2 +- .../tests/DataContractSerializer.cs | 1 + .../System.Runtime/System.Runtime.sln | 42 - .../System.Runtime/ref/System.Runtime.cs | 217 +- .../tests/System.Runtime.Tests.csproj | 7 - .../tests/System/DoubleTests.cs | 326 -- .../System.Runtime/tests/System/HalfTests.cs | 437 +-- ....Runtime.ReflectionInvokeEmit.Tests.csproj | 18 - .../InvokeEmit/runtimeconfig.template.json | 5 - ...e.ReflectionInvokeInterpreted.Tests.csproj | 18 - .../runtimeconfig.template.json | 5 - .../tests/System/Reflection/PointerTests.cs | 1 + .../tests/System/SingleTests.cs | 325 -- .../tests/System/StringTests.cs | 17 - .../tests/System/TimeZoneInfoTests.cs | 2 - .../tests/System/Type/TypeTests.cs | 4 - .../System.Runtime/tests/default.rd.xml | 1 - .../src/System/Security/AccessControl/ACL.cs | 14 +- .../Security/AccessControl/Privilege.cs | 8 +- .../AccessControl/SecurityDescriptor.cs | 2 +- .../System.Security.Cryptography.Cose.csproj | 6 - .../Cryptography/Cose/CoseHeaderLabel.cs | 8 +- .../Cryptography/Cose/CoseHeaderMap.cs | 6 +- .../Cryptography/Cose/CoseSign1Message.cs | 2 +- .../tests/CoseHeaderLabelTests.cs | 36 +- .../Cryptography/Pal/AnyOS/ManagedPal.Asn.cs | 2 +- .../Windows/DecryptorPalWindows.Decrypt.cs | 2 +- .../Pal/Windows/PkcsPalWindows.Encrypt.cs | 2 +- .../src/Internal/Cryptography/PkcsHelpers.cs | 5 +- .../Cryptography/Pkcs/EnvelopedCms.cs | 2 +- .../DynamicRevocationTests.Android.cs | 2 +- ...Cryptography.X509Certificates.Tests.csproj | 14 + .../tests/X509StoreTests.Unix.cs | 2 +- .../Security/Cryptography/Xml/EncryptedXml.cs | 4 +- .../Security/Cryptography/Xml/Reference.cs | 3 +- .../Security/Cryptography/Xml/SignedXml.cs | 6 +- .../Cryptography/Xml/SignedXmlDebugLog.cs | 2 +- .../Cryptography/Xml/XmlDsigXPathTransform.cs | 2 +- .../ref/System.Security.Cryptography.cs | 6 + .../src/System.Security.Cryptography.csproj | 6 +- .../Cryptography/AppleCCCryptorLite.cs | 52 +- .../Security/Cryptography/AsnEncodedData.cs | 21 +- .../Cryptography/CapiHelper.Windows.cs | 4 +- .../Security/Cryptography/CryptoConfig.cs | 17 +- .../Security/Cryptography/CryptoStream.cs | 2 +- .../DESCryptoServiceProvider.Windows.cs | 4 +- .../Security/Cryptography/ECDsaCng.Key.cs | 6 +- .../Security/Cryptography/HMACCommon.cs | 16 +- .../HMACHashProvider.Browser.Managed.cs | 130 - .../HMACHashProvider.Browser.Native.cs | 99 - .../System/Security/Cryptography/HMACSHA1.cs | 1 + .../Security/Cryptography/HMACSHA256.cs | 1 + .../Security/Cryptography/HMACSHA384.cs | 1 + .../Security/Cryptography/HMACSHA512.cs | 1 + .../HashProviderDispenser.Browser.cs | 40 +- .../Security/Cryptography/IncrementalHash.cs | 2 + .../RC2CryptoServiceProvider.Windows.cs | 4 +- .../SHAHashProvider.Browser.Native.cs | 52 +- .../CertificatePal.Windows.cs | 14 +- .../X509Certificates/CertificatePolicy.cs | 6 +- ...inPal.Windows.GetChainStatusInformation.cs | 4 +- .../ManagedX509ExtensionProcessor.cs | 2 +- .../OpenSslCertificateAssetDownloader.cs | 3 +- .../OpenSslDirectoryBasedStoreProvider.cs | 95 +- .../X509Certificates/OpenSslPkcs12Reader.cs | 1 - .../RSAPkcs1X509SignatureGenerator.cs | 3 +- .../StorePal.Android.AndroidKeyStore.cs | 6 +- .../X509Certificates/StorePal.iOS.cs | 2 +- ...X509AuthorityInformationAccessExtension.cs | 8 +- .../X509BasicConstraintsExtension.cs | 2 +- .../X509EnhancedKeyUsageExtension.cs | 2 +- .../X509Certificates/X509Extension.cs | 12 - .../X509Certificates/X509KeyUsageExtension.cs | 2 +- .../X509SubjectKeyIdentifierExtension.cs | 6 +- .../tests/BlockSizeValueTests.cs | 2 +- .../tests/CryptoConfigTests.cs | 24 +- .../tests/HmacMD5Tests.cs | 10 - .../tests/HmacSha1Tests.cs | 11 +- .../tests/HmacSha256Tests.cs | 11 +- .../tests/HmacSha384Tests.cs | 11 +- .../tests/HmacSha512Tests.cs | 11 +- .../tests/HmacTests.cs | 1 + .../tests/IncrementalHashTests.cs | 29 +- .../tests/InvalidUsageTests.cs | 1 + .../tests/ReusabilityTests.cs | 24 +- .../tests/Rfc2202HmacTests.cs | 1 + .../tests/Rfc4231HmacTests.cs | 1 + .../System.Security.Cryptography.Tests.csproj | 6 +- .../tests/wasm.helix.targets | 35 - .../Permissions/PrincipalPermission.cs | 4 +- .../src/System/Security/Principal/SID.cs | 4 +- .../Syndication/Atom10FeedFormatter.cs | 6 +- .../Syndication/Rss20FeedFormatter.cs | 4 +- .../Syndication/SyndicationItem.cs | 2 +- .../src/System/ServiceProcess/ServiceBase.cs | 2 +- .../src/Internal/AsyncSerializedWorker.cs | 4 +- .../src/Internal/ObjectToken/ObjectToken.cs | 4 +- .../System.Speech/src/Internal/RBList.cs | 4 +- .../src/Internal/SrgsCompiler/BackEnd.cs | 6 +- .../Internal/SrgsParser/SrgsDocumentParser.cs | 2 +- .../src/Internal/SrgsParser/XmlParser.cs | 5 +- .../Synthesis/AudioFormatConverter.cs | 7 +- .../src/Internal/Synthesis/SSmlParser.cs | 4 +- .../src/Internal/Synthesis/VoiceSynthesis.cs | 4 +- .../System.Speech/src/Recognition/Grammar.cs | 6 +- .../src/Recognition/RecognizerBase.cs | 21 +- .../Recognition/SpeechRecognitionEngine.cs | 66 +- .../src/Recognition/SpeechRecognizer.cs | 66 +- .../SrgsGrammar/SrgsElementFactory.cs | 2 +- .../Recognition/SrgsGrammar/SrgsGrammar.cs | 2 +- .../src/Result/RecognizedPhrase.cs | 2 +- .../src/Synthesis/PromptBuilder.cs | 2 +- .../System.Speech/src/Synthesis/VoiceInfo.cs | 2 +- .../src/System/Text/DBCSCodePageEncoding.cs | 2 +- .../src/System/Text/EUCJPEncoding.cs | 12 +- .../src/System/Text/EncodingByteBuffer.cs | 3 +- .../src/System/Text/EncodingNLS.cs | 10 +- .../src/System/Text/ISO2022Encoding.cs | 14 +- .../src/System/Text/SBCSCodePageEncoding.cs | 2 +- .../System/Text/Encodings/Web/TextEncoder.cs | 4 +- .../gen/JsonSourceGenerator.Emitter.cs | 260 +- .../gen/JsonSourceGenerator.Parser.cs | 14 +- .../gen/PropertyGenerationSpec.cs | 7 - .../gen/Reflection/FieldInfoWrapper.cs | 5 - .../gen/Reflection/PropertyInfoWrapper.cs | 7 +- .../gen/TypeGenerationSpec.cs | 5 - .../System.Text.Json/ref/System.Text.Json.cs | 65 +- src/libraries/System.Text.Json/src/README.md | 11 - .../src/Resources/Strings.resx | 87 +- .../src/System.Text.Json.csproj | 30 +- .../src/System/Text/Json/BitStack.cs | 2 +- .../JsonPropertyDictionary.KeyCollection.cs | 10 +- .../JsonPropertyDictionary.ValueCollection.cs | 10 +- .../Text/Json/JsonPropertyDictionary.cs | 26 +- .../JsonPropertyInfoDictionaryValueList.cs | 206 - .../Json/Serialization/ConfigurationList.cs | 41 +- .../Converters/CastingConverter.cs | 70 - .../Collection/JsonCollectionConverter.cs | 6 +- .../Collection/JsonDictionaryConverter.cs | 2 +- .../Collection/StackOrQueueConverter.cs | 2 +- .../FSharp/FSharpTypeConverterFactory.cs | 4 +- .../JsonMetadataServicesConverter.cs | 12 +- .../Converters/Object/ObjectConverter.cs | 2 +- .../Object/ObjectDefaultConverter.cs | 20 +- ...ctWithParameterizedConstructorConverter.cs | 15 +- .../Value/NullableConverterFactory.cs | 2 +- .../Text/Json/Serialization/JsonConverter.cs | 19 +- .../Serialization/JsonConverterFactory.cs | 8 +- .../Json/Serialization/JsonConverterOfT.cs | 44 +- .../JsonSerializer.Read.HandlePropertyName.cs | 10 +- .../JsonSerializer.Read.Helpers.cs | 2 +- .../JsonSerializer.Read.Stream.cs | 174 +- .../JsonSerializer.Read.Utf8JsonReader.cs | 2 +- .../JsonSerializer.Write.Helpers.cs | 8 +- .../Serialization/JsonSerializerContext.cs | 22 +- .../JsonSerializerOptions.Caching.cs | 61 +- .../JsonSerializerOptions.Converters.cs | 275 +- .../Serialization/JsonSerializerOptions.cs | 180 +- .../Metadata/CustomJsonTypeInfoOfT.cs | 47 - .../DefaultJsonTypeInfoResolver.Converters.cs | 126 - .../Metadata/DefaultJsonTypeInfoResolver.cs | 138 - .../Metadata/IJsonTypeInfoResolver.cs | 24 - .../JsonMetadataServices.Converters.cs | 32 +- .../Metadata/JsonMetadataServices.cs | 27 +- .../Metadata/JsonParameterInfo.cs | 2 +- .../Metadata/JsonPropertyInfo.cs | 259 +- .../Metadata/JsonPropertyInfoOfT.cs | 357 +- .../Metadata/JsonTypeInfo.Cache.cs | 17 +- .../Serialization/Metadata/JsonTypeInfo.cs | 294 +- .../Metadata/JsonTypeInfoKind.cs | 28 - .../Serialization/Metadata/JsonTypeInfoOfT.cs | 54 +- .../Metadata/JsonTypeInfoResolver.cs | 67 - .../Serialization/Metadata/MemberAccessor.cs | 2 +- .../ReflectionEmitCachingMemberAccessor.cs | 2 +- .../Metadata/ReflectionEmitMemberAccessor.cs | 4 +- .../Metadata/ReflectionJsonTypeInfoOfT.cs | 70 +- .../Metadata/ReflectionMemberAccessor.cs | 4 +- .../Metadata/SourceGenJsonTypeInfoOfT.cs | 43 +- .../Json/Serialization/ReadBufferState.cs | 162 +- .../Text/Json/Serialization/ReadStack.cs | 10 +- .../Text/Json/Serialization/WriteStack.cs | 2 +- .../Json/Serialization/WriteStackFrame.cs | 6 +- .../src/System/Text/Json/ThrowHelper.Node.cs | 24 +- .../Text/Json/ThrowHelper.Serialization.cs | 69 +- .../src/System/Text/Json/ThrowHelper.cs | 12 - .../tests/Common/PropertyVisibilityTests.cs | 4 +- .../JsonSerializerContextTests.cs | 232 +- .../JsonSourceGeneratorTests.cs | 66 +- .../Serialization/CacheTests.cs | 1 - .../CustomConverterTests.cs | 8 +- .../JsonSerializerWrapper.Reflection.cs | 18 +- ...ltJsonTypeInfoResolverMultiContextTests.cs | 134 - ...nTypeInfoResolverTests.JsonPropertyInfo.cs | 1153 ------ ...tJsonTypeInfoResolverTests.JsonTypeInfo.cs | 830 ---- .../DefaultJsonTypeInfoResolverTests.cs | 225 -- .../JsonTypeInfoResolverTests.cs | 130 - .../MetadataTests/MetadataTests.Options.cs | 6 +- .../MetadataTests/TestResolver.cs | 22 - .../Serialization/OptionsTests.cs | 145 +- .../Stream.DeserializeAsyncEnumerable.cs | 17 +- .../TypeInfoResolverFunctionalTests.cs | 703 ---- .../System.Text.Json.Tests.csproj | 8 - .../gen/Resources/xlf/Strings.cs.xlf | 4 +- .../gen/Resources/xlf/Strings.de.xlf | 4 +- .../gen/Resources/xlf/Strings.es.xlf | 4 +- .../gen/Resources/xlf/Strings.fr.xlf | 4 +- .../gen/Resources/xlf/Strings.it.xlf | 4 +- .../gen/Resources/xlf/Strings.ja.xlf | 4 +- .../gen/Resources/xlf/Strings.ko.xlf | 4 +- .../gen/Resources/xlf/Strings.pl.xlf | 4 +- .../gen/Resources/xlf/Strings.pt-BR.xlf | 4 +- .../gen/Resources/xlf/Strings.ru.xlf | 4 +- .../gen/Resources/xlf/Strings.tr.xlf | 4 +- .../gen/Resources/xlf/Strings.zh-Hans.xlf | 4 +- .../gen/Resources/xlf/Strings.zh-Hant.xlf | 4 +- .../gen/UpgradeToRegexGeneratorAnalyzer.cs | 25 +- .../src/Resources/Strings.resx | 3 + .../Text/RegularExpressions/RegexNode.cs | 2 +- ...ystem.Text.RegularExpressions.Tests.csproj | 7 +- .../CSharpCodeFixVerifier`2.cs | 4 +- .../tests/UnitTests/Stubs.cs | 15 + ....Text.RegularExpressions.Unit.Tests.csproj | 12 + .../UpgradeToRegexGeneratorAnalyzerTests.cs | 32 +- .../ref/System.Threading.RateLimiting.cs | 70 +- .../src/System.Threading.RateLimiting.csproj | 2 - .../ChainedPartitionedRateLimiter.cs | 248 -- .../DefaultPartitionedRateLimiter.cs | 276 -- .../RateLimiting/PartitionedRateLimiter.cs | 218 +- .../RateLimiting/RateLimitPartition.T.cs | 5 +- .../RateLimiting/RateLimitPartition.cs | 57 - .../tests/ChainedLimiterTests.cs | 1085 ------ .../tests/Infrastructure/Utils.cs | 228 -- .../tests/PartitionedRateLimiterTests.cs | 241 +- .../tests/RateLimiterPartitionTests.cs | 49 +- ...System.Threading.RateLimiting.Tests.csproj | 2 - .../src/Blocks/ActionBlock.cs | 2 +- .../src/Blocks/BatchBlock.cs | 4 +- .../src/Blocks/BroadcastBlock.cs | 2 +- .../src/Blocks/BufferBlock.cs | 4 +- .../src/Internal/SourceCore.cs | 7 +- .../src/Internal/TargetCore.cs | 2 +- .../src/System/Threading/Tasks/Parallel.cs | 4 +- .../tests/ThreadPoolTests.cs | 92 - .../src/System/Threading/Barrier.cs | 2 +- ...iCompatBaseline.NetCoreAppLatestStable.txt | 22 +- src/libraries/externals.csproj | 2 +- src/libraries/sendtohelix-wasm.targets | 143 +- src/libraries/tests.proj | 216 +- src/mono/CMakeLists.txt | 16 +- .../System.Private.CoreLib.csproj | 6 +- ...rce.PortableThreadPool.NativeSinks.Mono.cs | 4 - .../src/System/Exception.Mono.cs | 17 +- .../src/System/Reflection/CustomAttribute.cs | 4 +- .../Reflection/Emit/FieldBuilder.Mono.cs | 2 +- .../Reflection/Emit/ILGenerator.Mono.cs | 2 +- .../System/Reflection/Emit/MonoArrayMethod.cs | 4 +- .../Reflection/Metadata/MetadataUpdater.cs | 9 +- .../src/System/RuntimeType.Mono.cs | 7 +- .../src/System/String.Mono.cs | 4 +- src/mono/cmake/config.h.in | 4 + src/mono/mono.proj | 9 - src/mono/mono/arch/ppc/ppc-codegen.h | 9 +- src/mono/mono/component/debugger-agent.c | 10 +- src/mono/mono/component/debugger-protocol.h | 6 +- .../mono/component/debugger-state-machine.c | 2 +- src/mono/mono/component/event_pipe-stub.c | 20 - src/mono/mono/component/event_pipe.c | 1 - src/mono/mono/component/event_pipe.h | 9 - src/mono/mono/component/hot_reload-stub.c | 29 +- src/mono/mono/component/hot_reload.c | 151 +- src/mono/mono/component/hot_reload.h | 6 +- src/mono/mono/component/mini-wasm-debugger.c | 20 +- src/mono/mono/eglib/garray.c | 2 +- src/mono/mono/eglib/gdir-unix.c | 2 +- src/mono/mono/eglib/gfile.c | 2 +- src/mono/mono/eglib/giconv.c | 4 +- src/mono/mono/eglib/glib.h | 18 - src/mono/mono/eglib/gptrarray.c | 2 +- src/mono/mono/eventpipe/ep-rt-mono.c | 48 +- src/mono/mono/eventpipe/ep-rt-mono.h | 10 +- .../mono/eventpipe/gen-eventing-event-inc.lst | 1 - .../mono/metadata/assembly-load-context.c | 2 +- src/mono/mono/metadata/assembly.c | 3 +- src/mono/mono/metadata/class-init.c | 36 +- src/mono/mono/metadata/class.c | 9 +- src/mono/mono/metadata/custom-attrs.c | 21 +- src/mono/mono/metadata/debug-helpers.c | 15 +- src/mono/mono/metadata/debug-mono-ppdb.c | 22 +- src/mono/mono/metadata/dynamic-image.c | 3 +- src/mono/mono/metadata/dynamic-stream.c | 4 +- src/mono/mono/metadata/exception.c | 5 +- src/mono/mono/metadata/icall-decl.h | 2 - src/mono/mono/metadata/icall-def.h | 2 - src/mono/mono/metadata/icall-eventpipe.c | 33 +- src/mono/mono/metadata/icall.c | 36 +- src/mono/mono/metadata/image-internals.h | 4 +- src/mono/mono/metadata/image.c | 16 +- src/mono/mono/metadata/loader.c | 9 +- src/mono/mono/metadata/marshal.c | 33 +- src/mono/mono/metadata/memory-manager.c | 10 +- src/mono/mono/metadata/metadata-internals.h | 21 +- src/mono/mono/metadata/metadata-update.c | 16 +- src/mono/mono/metadata/metadata-update.h | 3 - src/mono/mono/metadata/metadata.c | 93 +- src/mono/mono/metadata/mono-basic-block.c | 9 +- src/mono/mono/metadata/mono-debug.c | 13 - src/mono/mono/metadata/mono-hash.c | 17 +- src/mono/mono/metadata/object-internals.h | 2 +- src/mono/mono/metadata/object.c | 17 +- src/mono/mono/metadata/reflection.c | 41 +- src/mono/mono/metadata/sre-encode.c | 3 +- src/mono/mono/metadata/threads.c | 86 +- src/mono/mono/mini/CMakeLists.txt | 21 - src/mono/mono/mini/abcremoval.c | 5 +- src/mono/mono/mini/alias-analysis.c | 9 +- src/mono/mono/mini/aot-compiler.c | 54 +- src/mono/mono/mini/branch-opts.c | 3 +- src/mono/mono/mini/cfgdump.c | 4 +- src/mono/mono/mini/debug-mini.c | 2 +- src/mono/mono/mini/decompose.c | 2 +- src/mono/mono/mini/driver.c | 25 +- src/mono/mono/mini/dwarfwriter.c | 2 +- src/mono/mono/mini/exceptions-amd64.c | 4 +- src/mono/mono/mini/exceptions-ppc.c | 9 - src/mono/mono/mini/genmdesc.py | 1 - src/mono/mono/mini/graph.c | 4 +- src/mono/mono/mini/helpers.c | 2 +- src/mono/mono/mini/interp/interp.c | 1 - src/mono/mono/mini/interp/transform.c | 4 +- src/mono/mono/mini/intrinsics.c | 5 - src/mono/mono/mini/ir-emit.h | 2 +- src/mono/mono/mini/linear-scan.c | 4 +- src/mono/mono/mini/lldb.c | 10 +- src/mono/mono/mini/mini-amd64-gsharedvt.c | 9 +- src/mono/mono/mini/mini-amd64.c | 60 +- src/mono/mono/mini/mini-arm.c | 58 +- src/mono/mono/mini/mini-arm64.c | 14 +- src/mono/mono/mini/mini-exceptions.c | 6 +- src/mono/mono/mini/mini-generic-sharing.c | 8 +- src/mono/mono/mini/mini-llvm.c | 20 +- src/mono/mono/mini/mini-ops.h | 2 +- src/mono/mono/mini/mini-ppc.c | 161 +- src/mono/mono/mini/mini-ppc.h | 20 +- src/mono/mono/mini/mini-profiler.c | 2 +- src/mono/mono/mini/mini-runtime.c | 16 +- src/mono/mono/mini/mini-unwind.h | 16 +- src/mono/mono/mini/mini-wasm.c | 14 +- src/mono/mono/mini/mini-wasm.h | 2 - src/mono/mono/mini/mini-x86.c | 4 +- src/mono/mono/mini/mini.c | 2 +- src/mono/mono/mini/mini.h | 11 +- src/mono/mono/mini/monovm.c | 2 +- src/mono/mono/mini/seq-points.c | 8 +- src/mono/mono/mini/tramp-ppc.c | 4 +- src/mono/mono/mini/unwind.c | 2 +- src/mono/mono/profiler/aot.c | 13 +- src/mono/mono/profiler/log.c | 10 +- src/mono/mono/utils/CMakeLists.txt | 6 +- src/mono/mono/utils/lock-free-alloc.c | 12 +- src/mono/mono/utils/mono-context.h | 6 +- src/mono/mono/utils/mono-flight-recorder.c | 6 +- src/mono/mono/utils/mono-poll.c | 6 +- src/mono/mono/utils/mono-rand.c | 2 +- src/mono/mono/utils/mono-sigcontext.h | 4 +- src/mono/mono/utils/mono-threads.c | 2 +- src/mono/mono/utils/monobitset.h | 6 +- src/mono/mono/utils/options-def.h | 3 +- src/mono/sample/HelloWorld/HelloWorld.csproj | 30 - src/mono/sample/HelloWorld/Makefile | 15 +- src/mono/wasm/build/WasmApp.Native.targets | 1 - src/mono/wasm/build/WasmApp.targets | 5 +- .../BrowserDebugHost/BrowserDebugHost.csproj | 1 - .../debugger/BrowserDebugProxy/DebugStore.cs | 74 +- .../BrowserDebugProxy/DevToolsHelper.cs | 3 +- .../Firefox/FirefoxExecutionContext.cs | 2 +- .../Firefox/FirefoxMonoProxy.cs | 4 +- .../MemberReferenceResolver.cs | 2 +- .../debugger/BrowserDebugProxy/MonoProxy.cs | 115 +- .../BrowserDebugProxy/MonoSDBHelper.cs | 38 +- .../BrowserDebugProxy/ProxyOptions.cs | 4 +- src/mono/wasm/host/Options.cs | 4 +- src/mono/wasm/host/WasmAppHost.csproj | 1 - src/mono/wasm/runtime/CMakeLists.txt | 2 - src/mono/wasm/runtime/cjs/dotnet.cjs.lib.js | 3 +- src/mono/wasm/runtime/crypto-worker.ts | 23 +- .../{workers => }/dotnet-crypto-worker.js | 48 +- src/mono/wasm/runtime/driver.c | 18 - src/mono/wasm/runtime/es6/dotnet.es6.lib.js | 3 +- src/mono/wasm/runtime/exports.ts | 9 +- src/mono/wasm/runtime/guarded-promise.ts | 34 - src/mono/wasm/runtime/js-to-cs.ts | 5 +- src/mono/wasm/runtime/package-lock.json | 2113 +--------- src/mono/wasm/runtime/package.json | 1 - src/mono/wasm/runtime/rollup.config.js | 53 +- src/mono/wasm/runtime/startup.ts | 7 +- src/mono/wasm/runtime/workers/README.md | 31 - src/mono/wasm/runtime/workers/tsconfig.json | 13 - src/mono/wasm/test-main.js | 25 +- src/mono/wasm/wasm.proj | 6 +- .../corehost/apphost/apphost.windows.cpp | 6 +- src/native/corehost/corehost.cpp | 4 +- src/native/corehost/deps_format.cpp | 2 +- src/native/corehost/dotnet/CMakeLists.txt | 3 +- src/native/corehost/dotnet/dotnet.ico | Bin 45150 -> 0 bytes src/native/corehost/dotnet/dotnet.rc | 1 - src/native/corehost/fxr/command_line.cpp | 58 +- src/native/corehost/fxr/command_line.h | 2 +- src/native/corehost/fxr/files.cmake | 2 - src/native/corehost/fxr/fx_muxer.cpp | 8 +- src/native/corehost/fxr/fx_resolver.cpp | 2 +- .../corehost/fxr/fx_resolver.messages.cpp | 4 +- src/native/corehost/fxr/install_info.cpp | 59 - src/native/corehost/fxr/install_info.h | 15 - src/native/corehost/fxr/sdk_resolver.cpp | 9 + src/native/corehost/fxr/sdk_resolver.h | 1 + src/native/corehost/fxr_resolver.cpp | 4 +- src/native/corehost/hostmisc/pal.h | 26 +- src/native/corehost/hostmisc/pal.unix.cpp | 77 +- src/native/corehost/hostmisc/pal.windows.cpp | 73 +- src/native/corehost/hostmisc/utils.cpp | 60 +- src/native/corehost/hostmisc/utils.h | 15 +- src/native/corehost/hostpolicy/args.cpp | 8 +- .../corehost/hostpolicy/deps_resolver.cpp | 2 +- src/native/corehost/hostpolicy/hostpolicy.cpp | 2 +- src/native/eventpipe/ds-ipc-pal-socket.c | 6 +- src/native/eventpipe/ep-event-source.c | 2 - src/native/external/libunwind.cmake | 40 - src/native/external/libunwind/CMakeLists.txt | 5 - .../external/libunwind/src/CMakeLists.txt | 33 - .../external/libunwind_extras/CMakeLists.txt | 2 - src/native/external/zlib-intel.cmake | 4 +- src/native/external/zlib.cmake | 4 +- src/native/libs/Common/pal_config.h.in | 1 + .../pal_localeStringData.c | 74 +- .../libs/System.Native/pal_networking.c | 3 +- .../System.Native/pal_runtimeinformation.c | 6 - .../System.Net.Security.Native/pal_gssapi.c | 30 + .../pal_x509chain.c | 6 +- .../pal_x509chain.h | 5 + .../entrypoints.c | 1 + .../pal_symmetric.c | 21 + .../pal_symmetric.h | 8 + .../pal_crypto_webworker.c | 27 +- .../pal_crypto_webworker.h | 11 +- src/native/libs/configure.cmake | 12 + .../metadata/details/assembly-functions.h | 1 - .../mono/metadata/details/image-functions.h | 4 +- src/tasks/AotCompilerTask/MonoAOTCompiler.cs | 99 +- .../BlazorWasmBuildPublishTests.cs | 9 +- .../Wasm.Build.Tests/BuildEnvironment.cs | 1 + .../Wasm.Build.Tests/MainWithArgsTests.cs | 2 + .../Wasm.Build.Tests/NativeLibraryTests.cs | 9 +- .../ReferenceNewAssemblyRebuildTest.cs | 1 + .../SatelliteAssembliesTests.cs | 47 +- .../Wasm.Build.Tests/WasmBuildAppTest.cs | 2 + .../Wasm.Build.Tests/WasmTemplateTests.cs | 1 - src/tests/Common/testenvironment.proj | 5 +- .../Interop/COM/ComWrappers/API/Program.cs | 4 - .../COM/ExtensionPoints/ExtensionPoints.cs | 82 - .../ExtensionPoints/ExtensionPoints.csproj | 10 - .../Interop/COM/ExtensionPoints/Interfaces.cs | 78 - .../COM/NETClients/Primitives/ErrorTests.cs | 27 +- .../COM/NETServer/ErrorMarshalTesting.cs | 9 - .../NativeClients/Primitives/ErrorTests.cpp | 39 - .../COM/NativeServer/ErrorMarshalTesting.h | 30 +- .../COM/ServerContracts/Server.Contracts.cs | 2 - .../COM/ServerContracts/Server.Contracts.h | 4 - src/tests/JIT/Directed/RVAInit/nested.ilproj | 2 - src/tests/JIT/Directed/RVAInit/simple.ilproj | 2 - .../StructABI/MisSizedStructs_ArmSplit.cs | 124 - .../StructABI/MisSizedStructs_ArmSplit.csproj | 13 - .../Directed/StructABI/TypeMismatchedArgs.cs | 67 - .../General/HwiOp/HwiValueNumbering.cs | 218 -- .../General/HwiOp/HwiValueNumbering.csproj | 11 - src/tests/JIT/Intrinsics/BMI1Intrinsics.cs | 40 +- .../JitBlue/Runtime_61074/Runtime_61074.cs | 45 - .../Runtime_61074/Runtime_61074.csproj | 9 - .../JitBlue/Runtime_63905/Runtime_63905.cs | 46 - .../Runtime_63905/Runtime_63905.csproj | 9 - .../JitBlue/Runtime_65937/Runtime_65937.cs | 71 - .../Runtime_65937/Runtime_65937.csproj | 11 - .../JitBlue/Runtime_66089/Runtime_66089.cs | 78 - .../Runtime_66089/Runtime_66089.csproj | 10 - .../JitBlue/Runtime_68136/Runtime_68136.cs | 37 - .../Runtime_68136/Runtime_68136.csproj | 11 - .../JitBlue/Runtime_68568/Runtime_68568.il | 107 - .../Runtime_68568/Runtime_68568.ilproj | 12 - .../JitBlue/Runtime_70333/Runtime_70333.cs | 28 - .../Runtime_70333/Runtime_70333.csproj | 9 - .../JitBlue/Runtime_70466/Runtime_70466.cs | 38 - .../Runtime_70466/Runtime_70466.csproj | 9 - .../JitBlue/Runtime_70790/Runtime_70790.cs | 40 - .../Runtime_70790/Runtime_70790.csproj | 18 - .../JitBlue/Runtime_70824/Runtime_70824.cs | 48 - .../Runtime_70824/Runtime_70824.csproj | 10 - .../JitBlue/Runtime_70954/Runtime_70954.cs | 32 - .../Runtime_70954/Runtime_70954.csproj | 10 - src/tests/JIT/opt/Cloning/Runtime_70802.cs | 64 - .../JIT/opt/Cloning/Runtime_70802.csproj | 19 - src/tests/JIT/opt/Compares/compares.cs | 204 - src/tests/JIT/opt/Compares/compares.csproj | 12 - ...amondshape.cs.template => diamondshape.cs} | 0 ...cmethods.cs.template => genericmethods.cs} | 0 .../{methodimpl.cs.template => methodimpl.cs} | 0 ... non_virtual_calls_to_instance_methods.cs} | 0 ...generics.cs.template => sharedgenerics.cs} | 0 .../simple/{simple.cs.template => simple.cs} | 0 .../{valuetypes.cs.template => valuetypes.cs} | 0 .../RegressionTests/GitHub_70385.cs.template | 36 - .../RegressionTests/GitHub_70385.il | 135 - .../RegressionTests/GitHub_70385.ilproj | 11 - .../exceptioninterop/CMakeLists.txt | 4 - .../exceptioninterop/ExceptionInterop.cs | 125 - .../exceptioninterop/ExceptionInterop.csproj | 10 - .../ExceptionInteropNative.cpp | 19 - .../ExceptionInterop_ro.csproj | 14 - .../InvalidOperations.csproj | 12 - .../invalid_operations/ManagedPointers.cs | 84 - src/tests/ilverify/ILVerificationTests.csproj | 2 +- src/tests/issues.targets | 22 +- .../nativeaot/SmokeTests/Dataflow/Dataflow.cs | 9 +- .../DeadCodeElimination.cs | 72 +- .../SmokeTests/DynamicGenerics/rd.xml | 21 - .../Preinitialization.csproj | 6 - .../SmokeTests/Reflection/Reflection.cs | 250 +- .../SmokeTests/Reflection/Reflection.csproj | 1 + ...csproj => Reflection_ReflectedOnly.csproj} | 7 +- .../profiler/native/gcprofiler/gcprofiler.cpp | 9 +- ...icrosoft.Diagnostics.NETCore.Client.csproj | 8 +- 2950 files changed, 33405 insertions(+), 57573 deletions(-) delete mode 100644 docs/coding-guidelines/mono-code-guide.md delete mode 100644 docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md delete mode 100644 docs/design/security/unix-tmp.md delete mode 100644 src/coreclr/debug/daccess/ppc64le/primitives.cpp delete mode 100644 src/coreclr/debug/ee/ppc64le/dbghelpers.S delete mode 100644 src/coreclr/debug/ee/ppc64le/primitives.cpp delete mode 100644 src/coreclr/debug/shared/ppc64le/primitives.cpp create mode 100644 src/coreclr/inc/contxt.h create mode 100644 src/coreclr/inc/defaultallocator.h create mode 100644 src/coreclr/inc/regex_base.h create mode 100644 src/coreclr/inc/regex_util.h create mode 100644 src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceModeOnlyAttribute.cs create mode 100644 src/coreclr/nativeaot/System.Private.CoreLib/src/System/Helpers.cs create mode 100644 src/coreclr/nativeaot/System.Private.Reflection.Core/src/ILLink/ILLink.Substitutions.xml rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/Internal/Reflection/Core/Execution/ExecutionEnvironment.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/Internal/Reflection/Core/Execution/FieldAccessor.cs (92%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/Internal/Reflection/Core/Execution/MethodInvoker.cs (81%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/Internal/Reflection/Core/Execution/ReflectionCoreExecution.cs (95%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/Internal/Reflection/Core/ReflectionDomainSetup.cs (88%) create mode 100644 src/coreclr/nativeaot/System.Private.Reflection.Core/src/Resources/Strings.resx create mode 100644 src/coreclr/nativeaot/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/ActivatorImplementation.cs (94%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs (94%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs (68%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs (95%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/MemberTypeIndex.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs (93%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.NativeFormat.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs (86%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.Enumerator.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs (94%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/Dispenser.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/Assignability.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/BlockedRuntimeTypeNameGenerator.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/Dispensers.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/Helpers.NativeFormat.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/Helpers.cs (94%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/IRuntimeMemberInfoWithNoMetadataDefinition.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/ListBuilder.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/NamespaceChain.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs (93%) create mode 100644 src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/QSignatureTypeHandle.NativeFormat.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs (87%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/RuntimeTypeHandleKey.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/ThunkedApis.cs (95%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/ToStringUtils.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/TypeContext.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/TypeForwardInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs (85%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/TypeResolver.cs (95%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/General/TypeUnifier.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs (95%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs (94%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs (93%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/IRuntimeMethodCommon.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/InvokerOptions.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/NativeFormat/NativeFormatMethodCommon.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs (86%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeClsIdNullaryConstructorInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs (94%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Modules/NativeFormat/NativeFormatRuntimeModule.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/Modules/RuntimeModule.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/PropertyInfos/EcmaFormat/EcmaFormatRuntimePropertyInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs (96%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs (96%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.UnificationKey.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.UnificationKey.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.UnificationKey.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeTypeInfo.CoreGetDeclared.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeByRefTypeInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.UnificationKey.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs (95%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.UnificationKey.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.UnificationKey.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs (95%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs (96%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs (98%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimePointerTypeInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeDefinitionTypeInfo.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs (96%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.GetMember.cs (84%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs (90%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs (97%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeParsing/GetTypeOptions.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs (100%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeParsing/TypeName.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.Reflection.Core}/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.TypeLoader}/src/Internal/Reflection/Core/AssemblyBinder.cs (92%) rename src/coreclr/nativeaot/{System.Private.CoreLib/src/System/Reflection/Runtime/General => System.Private.TypeLoader/src/Internal/Runtime/TypeLoader}/MetadataReaderExtensions.cs (96%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.TypeLoader}/src/System/Reflection/Runtime/General/QHandles.NativeFormat.cs (99%) rename src/coreclr/nativeaot/{System.Private.CoreLib => System.Private.TypeLoader}/src/System/Reflection/Runtime/General/QHandles.cs (93%) create mode 100644 src/coreclr/pal/inc/rt/intsafe.h delete mode 100644 src/coreclr/pal/inc/unixasmmacrosppc64le.inc delete mode 100644 src/coreclr/pal/src/arch/ppc64le/asmconstants.h delete mode 100644 src/coreclr/pal/src/arch/ppc64le/callsignalhandlerwrapper.S delete mode 100644 src/coreclr/pal/src/arch/ppc64le/context2.S delete mode 100644 src/coreclr/pal/src/arch/ppc64le/debugbreak.S delete mode 100644 src/coreclr/pal/src/arch/ppc64le/exceptionhelper.S delete mode 100644 src/coreclr/pal/src/arch/ppc64le/processor.cpp delete mode 100644 src/coreclr/pal/src/arch/ppc64le/signalhandlerhelper.cpp delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitution.cs delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs delete mode 100644 src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectableFieldNode.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseMemberAssertionAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/CreatedMemberAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DependencyRecordedAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DisplayNameAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/EnableLoggerAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExactlyResolvedDocumentationSignatureAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectGeneratedDocumentationSignatureAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectResolvedDocumentationSignatureAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectUnresolvedDocumentationSignatureAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceOnMemberInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedNoWarningsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptExportedTypeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptModuleReferenceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/NoLinkedOutputAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyReference.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedNameValueAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipKeptItemsValidationAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipRemainingErrorsValidationAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestCaseRequirementsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestRunCharacteristics.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/VerifyMetadataNamesAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowStringExtensions.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowTypeExtensions.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreDescriptorsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreLinkAttributesAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreSubstitutionsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkAttributesFile.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDefaultActionAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDescriptorFile.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerSubstitutionFileAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerTrimModeAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripDescriptorsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripLinkAttributesAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripSubstitutionsAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/IntrinsicAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/RemoveAttributeInstancesAttribute.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/EmptyArrayIntrinsicsDataFlow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeInfoDataFlow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/TypeInfoAsTypeDataFlow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/UnsafeDataFlow.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Repro/Program.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/CecilExtensions.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/NiceIO.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/Mono.Linker.Tests.csproj delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestCase.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestSuites.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/BaseMetadataProvider.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerDriver.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptions.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptionsBuilder.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerTestCaseResult.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILInputCompiler.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/IgnoreTestException.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/PathUtilities.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestLogWriter.cs delete mode 100644 src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs delete mode 100644 src/coreclr/unwinder/ppc64le/unwinder_ppc64le.cpp create mode 100644 src/coreclr/utilcode/iallocator.cpp create mode 100644 src/coreclr/vm/ctxtcall.h create mode 100644 src/coreclr/vm/dataimage.h delete mode 100644 src/coreclr/vm/ppc64le/unixstubs.cpp create mode 100644 src/coreclr/vm/sourceline.cpp create mode 100644 src/coreclr/vm/sourceline.h create mode 100644 src/coreclr/vm/stackcontents.h delete mode 100644 src/libraries/Common/src/Interop/Browser/System.Security.Cryptography.Native.Browser/Interop.Sign.cs create mode 100644 src/libraries/Common/src/Interop/Unix/System.Native/Interop.Permissions.cs rename src/libraries/Common/src/Interop/Windows/Kernel32/{Interop.GetCommandLine.cs => Interop.VerSetConditionMask.cs} (55%) create mode 100644 src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VerifyVersionExW.cs delete mode 100644 src/libraries/Common/src/Interop/Windows/Shell32/Interop.CommandLineToArgv.cs create mode 100644 src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.PlatformNotSupported.cs delete mode 100644 src/libraries/Common/src/System/Console/ConsoleUtils.cs delete mode 100644 src/libraries/Common/src/System/HashCodeRandomization.cs create mode 100644 src/libraries/Common/src/System/Net/ContextFlagsAdapterPal.PlatformNotSupported.cs create mode 100644 src/libraries/Common/src/System/Net/Security/NegotiateStreamPal.PlatformNotSupported.cs delete mode 100644 src/libraries/Common/tests/System/Net/Security/FakeNegotiateServer.cs delete mode 100644 src/libraries/Common/tests/System/Reflection/InvokeEmitTests.cs delete mode 100644 src/libraries/Common/tests/System/Reflection/InvokeInterpretedTests.cs delete mode 100644 src/libraries/Microsoft.Extensions.Logging.Console/src/ConsoleLoggerQueueFullMode.cs delete mode 100644 src/libraries/Microsoft.Extensions.Logging.Console/tests/Microsoft.Extensions.Logging.Console.Tests/ConsoleLoggerProcessorTests.cs delete mode 100644 src/libraries/System.Formats.Tar/src/System/Formats/Tar/PaxGlobalExtendedAttributesTarEntry.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarEntry/GnuTarEntry.Conversion.Tests.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarEntry/PaxTarEntry.Conversion.Tests.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarEntry/TarEntry.Conversion.Tests.Base.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarEntry/UstarTarEntry.Conversion.Tests.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarEntry/V7TarEntry.Conversion.Tests.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarReader/TarReader.ExtractToFile.Tests.Unix.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.GlobalExtendedAttributes.Tests.cs delete mode 100644 src/libraries/System.Formats.Tar/tests/TarReader/TarReader.File.Tests.Base.cs delete mode 100644 src/libraries/System.IO.FileSystem/tests/Base/BaseGetSetUnixFileMode.cs delete mode 100644 src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory_UnixFileMode.Unix.cs delete mode 100644 src/libraries/System.IO.FileSystem/tests/Directory/CreateDirectory_UnixFileMode.Windows.cs delete mode 100644 src/libraries/System.IO.FileSystem/tests/DirectoryInfo/GetSetUnixFileMode.cs delete mode 100644 src/libraries/System.IO.FileSystem/tests/File/GetSetUnixFileMode.cs delete mode 100644 src/libraries/System.IO.FileSystem/tests/File/GetSetUnixFileMode_SafeFileHandle.cs delete mode 100644 src/libraries/System.IO.FileSystem/tests/FileInfo/GetSetUnixFileMode.cs delete mode 100644 src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpClientJsonExtensions.Delete.cs create mode 100644 src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.NtAuth.tvOS.cs delete mode 100644 src/libraries/System.Net.Http/tests/FunctionalTests/NtAuthTests.FakeServer.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockConnection.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockImplementationProvider.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockListener.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Mock/MockStream.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicImplementationProvider.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicConnectionProvider.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicImplementationProvider.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicListenerProvider.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/QuicStreamProvider.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.Unsupported.cs create mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicImplementationProviders.cs delete mode 100644 src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs delete mode 100644 src/libraries/System.Net.Security/src/System/Net/Security/NegotiateAuthentication.cs delete mode 100644 src/libraries/System.Net.Security/src/System/Net/Security/NegotiateAuthenticationClientOptions.cs delete mode 100644 src/libraries/System.Net.Security/src/System/Net/Security/NegotiateAuthenticationServerOptions.cs delete mode 100644 src/libraries/System.Net.Security/src/System/Net/Security/NegotiateAuthenticationStatusCode.cs rename src/libraries/{Common/tests/System/Net/Security => System.Net.Security/tests/UnitTests/Fakes}/FakeNtlmServer.cs (96%) delete mode 100644 src/libraries/System.Net.Security/tests/UnitTests/NegotiateAuthenticationTests.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/IO/Directory.Unix.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/IO/Directory.Windows.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/IO/File.Unix.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/IO/File.Windows.cs delete mode 100644 src/libraries/System.Private.CoreLib/src/System/IO/UnixFileMode.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/2-(1)cnt19.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft 25.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft1.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft1.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft10a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft10b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft11a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft11b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft11c.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12c.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12d.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12e.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12f.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12g.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12h.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12i.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12j.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12k.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12l.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12m.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12n.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12o.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12p.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12q.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12r.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12s.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12t.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12u.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12v.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12w.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12x.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12y.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft12z.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft13.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft14a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft15a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft15b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft16.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft16.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft16.xslt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft17.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft18.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft18a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft18b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft19.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft19.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft19a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft2.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft20.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft20.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft20a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft21.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft21.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft21a.xml create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft22.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft22.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft23.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft23.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft24.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft24a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft24b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft25.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft26.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft26.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft27.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft28.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft29.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft3.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft30.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft31.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft31.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft32.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft33.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft34.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft35.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft36.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft37.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft38.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft4.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft5.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft6.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft7.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft8.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/bft9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cct1.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt1.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt1.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt10a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt10b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt11a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt11b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt12.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt12a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt12b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt13.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt14.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt14b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt15a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt15b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt16.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt17.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt18.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt18.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt18.xslt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt19.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt2.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt20.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt20.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt21.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt21.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt22.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt22.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt23.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt23.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt24.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt25.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt25a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt25b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt26.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt26a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt26b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt27.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt27a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt27b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt28.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt28a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt28b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt29.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt29a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt29b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt3.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt4.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt4.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt5.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt5.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt6.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt6.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt7.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt7.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt8.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt8a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt8b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt9a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/cnt9b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft1.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft1.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft10.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft11.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft12.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft12.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft13.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft14.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft15.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft16.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft16.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft17.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft17.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft18.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft18.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft19.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft19.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft2.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft20.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft20.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft21.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft21.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft22.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft22.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft23.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft23.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft3.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft4.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft4.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft5.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft5.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft6.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft6.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft7.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft7.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft8.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft8.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/dft9.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft10.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft11.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft12.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft12.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft13.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft14.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft15.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft16.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft16.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft17.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft17.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft18.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft18.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft19.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft2.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft20.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft21.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft3.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft4.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft4.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft5.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft6.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft6.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft7.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft7a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft7b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft8.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft8a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft8b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft8c.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft8d.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/fft9.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/help.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/identity.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft10b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft10c.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft11a.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft11b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft12.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft12b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft12c.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft13a.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft13b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft14b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft14c.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft15b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft15c.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft16---.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft17.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft18.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft4.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft5.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft6.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft7a.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft7b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft8a.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft8b.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft8c.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/infft9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/mail.xml create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/multith.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/ns1..cnt17.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/ns1.ns2.cnt16.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft1.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft1.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft10.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft11.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft12.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft12.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft13.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft14.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft15.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft16.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft16.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft17.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft17.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft18.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft18.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft19.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft19.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft2.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft20.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft20.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft21.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft21.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft22.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft22.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft23.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft23.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft25.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft25.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft27.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft27.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft28.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft28.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft29.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft29.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft3.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft30.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft30.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft31.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft31.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft4.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft4a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft4b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft5.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft5a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft5b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft6.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft6a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft6b.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft7.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft7.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft8.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft8.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/oft9.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft1.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft1.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft10.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft11.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft12.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft12.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft13.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft14.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft15.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft16.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft16.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft17.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft17.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft18.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft18.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft19.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft19.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft2.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft20.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft20.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft3.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft4.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft4.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft7.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft7.xsl delete mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft8.dll create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft8.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft8.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/pft9.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft1.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft1.xml create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft1.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft10.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft10.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft11.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft11.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft13.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft13.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft14.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft14.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft15.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft15.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft2.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft2.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft27.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft27.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft27a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft28.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft28.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft28a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft29.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft29.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft29a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft3.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft3.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft30.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft30.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft30a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft31.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft31.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft31a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft32.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft32.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft32a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft33.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft33.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft33a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft34.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft34.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft34a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft35.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft35.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft35a.xsl delete mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft36.dll create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft36.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft36.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft36a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft37.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft37.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft37a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft38.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft38.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft38a.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft4.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft4.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft41.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft41.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft42.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft42.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft43.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft43.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft44.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft44.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft45.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft45.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft46.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft46.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft47.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft47.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft48.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft48.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft49.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft49.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft5.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft5.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft50.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft50.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft6.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft6.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft7.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft7.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft8.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft8.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft9.txt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/baseline/sft9.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/precompiled/Scripting28.xsl create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/TestFiles/TestData/xsltc/precompiled/sft1.xml create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/ApiTests/XsltcApiTest.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestBasicFunctionality.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestCaseBase.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestFile.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestPlatform.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/CommonScenarios/XsltcTestSettings.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/Identity.xslt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/IdentityTransform.xslt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/TestStylesheet.xslt create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCommon.cs create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/XsltCompiler.Tests.csproj create mode 100644 src/libraries/System.Private.Xml/tests/Xslt/XsltCompiler/XsltcModule.cs delete mode 100644 src/libraries/System.Reflection.Emit.ILGeneration/tests/ILGenerator/Emit5Tests.cs create mode 100644 src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EmptyArray.cs delete mode 100644 src/libraries/System.Reflection.MetadataLoadContext/src/README.md delete mode 100644 src/libraries/System.Reflection/tests/InvokeEmit/System.Reflection.InvokeEmit.Tests.csproj delete mode 100644 src/libraries/System.Reflection/tests/InvokeEmit/runtimeconfig.template.json delete mode 100644 src/libraries/System.Reflection/tests/InvokeInterpreted/System.Reflection.InvokeInterpreted.Tests.csproj delete mode 100644 src/libraries/System.Reflection/tests/InvokeInterpreted/runtimeconfig.template.json delete mode 100644 src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.V1.cs delete mode 100644 src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomTypeMarshallingStrategy.cs delete mode 100644 src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/CustomTypeMarshallersAttributeBase.cs delete mode 100644 src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/ManagedToUnmanagedMarshallersAttribute.cs delete mode 100644 src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CustomMarshallingTests.V1.cs delete mode 100644 src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.V1.cs delete mode 100644 src/libraries/System.Runtime/tests/System/Reflection/InvokeEmit/System.Runtime.ReflectionInvokeEmit.Tests.csproj delete mode 100644 src/libraries/System.Runtime/tests/System/Reflection/InvokeEmit/runtimeconfig.template.json delete mode 100644 src/libraries/System.Runtime/tests/System/Reflection/InvokeInterpreted/System.Runtime.ReflectionInvokeInterpreted.Tests.csproj delete mode 100644 src/libraries/System.Runtime/tests/System/Reflection/InvokeInterpreted/runtimeconfig.template.json delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACHashProvider.Browser.Managed.cs delete mode 100644 src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACHashProvider.Browser.Native.cs delete mode 100644 src/libraries/System.Security.Cryptography/tests/wasm.helix.targets delete mode 100644 src/libraries/System.Text.Json/src/README.md delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/JsonPropertyInfoDictionaryValueList.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/CustomJsonTypeInfoOfT.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.Converters.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/DefaultJsonTypeInfoResolver.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/IJsonTypeInfoResolver.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoKind.cs delete mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoResolver.cs delete mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverMultiContextTests.cs delete mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonPropertyInfo.cs delete mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.JsonTypeInfo.cs delete mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/DefaultJsonTypeInfoResolverTests.cs delete mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/JsonTypeInfoResolverTests.cs delete mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/TestResolver.cs delete mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/TypeInfoResolverFunctionalTests.cs rename src/libraries/System.Text.RegularExpressions/tests/{FunctionalTests => UnitTests}/CSharpCodeFixVerifier`2.cs (96%) rename src/libraries/System.Text.RegularExpressions/tests/{FunctionalTests => UnitTests}/UpgradeToRegexGeneratorAnalyzerTests.cs (95%) delete mode 100644 src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/ChainedPartitionedRateLimiter.cs delete mode 100644 src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/DefaultPartitionedRateLimiter.cs delete mode 100644 src/libraries/System.Threading.RateLimiting/tests/ChainedLimiterTests.cs delete mode 100644 src/libraries/System.Threading.RateLimiting/tests/Infrastructure/Utils.cs rename src/mono/wasm/runtime/{workers => }/dotnet-crypto-worker.js (83%) delete mode 100644 src/mono/wasm/runtime/guarded-promise.ts delete mode 100644 src/mono/wasm/runtime/workers/README.md delete mode 100644 src/mono/wasm/runtime/workers/tsconfig.json delete mode 100644 src/native/corehost/dotnet/dotnet.ico delete mode 100644 src/native/corehost/dotnet/dotnet.rc delete mode 100644 src/native/corehost/fxr/install_info.cpp delete mode 100644 src/native/corehost/fxr/install_info.h delete mode 100644 src/tests/Interop/COM/ExtensionPoints/ExtensionPoints.cs delete mode 100644 src/tests/Interop/COM/ExtensionPoints/ExtensionPoints.csproj delete mode 100644 src/tests/Interop/COM/ExtensionPoints/Interfaces.cs delete mode 100644 src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.cs delete mode 100644 src/tests/JIT/Directed/StructABI/MisSizedStructs_ArmSplit.csproj delete mode 100644 src/tests/JIT/HardwareIntrinsics/General/HwiOp/HwiValueNumbering.cs delete mode 100644 src/tests/JIT/HardwareIntrinsics/General/HwiOp/HwiValueNumbering.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_61074/Runtime_61074.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_61074/Runtime_61074.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_63905/Runtime_63905.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_63905/Runtime_63905.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_65937/Runtime_65937.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_65937/Runtime_65937.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_66089/Runtime_66089.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_66089/Runtime_66089.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_68136/Runtime_68136.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_68136/Runtime_68136.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_68568/Runtime_68568.il delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_68568/Runtime_68568.ilproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70333/Runtime_70333.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70333/Runtime_70333.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70466/Runtime_70466.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70466/Runtime_70466.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70790/Runtime_70790.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70790/Runtime_70790.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70824/Runtime_70824.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70824/Runtime_70824.csproj delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70954/Runtime_70954.cs delete mode 100644 src/tests/JIT/Regression/JitBlue/Runtime_70954/Runtime_70954.csproj delete mode 100644 src/tests/JIT/opt/Cloning/Runtime_70802.cs delete mode 100644 src/tests/JIT/opt/Cloning/Runtime_70802.csproj delete mode 100644 src/tests/JIT/opt/Compares/compares.cs delete mode 100644 src/tests/JIT/opt/Compares/compares.csproj rename src/tests/Loader/classloader/DefaultInterfaceMethods/diamondshape/{diamondshape.cs.template => diamondshape.cs} (100%) rename src/tests/Loader/classloader/DefaultInterfaceMethods/genericmethods/{genericmethods.cs.template => genericmethods.cs} (100%) rename src/tests/Loader/classloader/DefaultInterfaceMethods/methodimpl/{methodimpl.cs.template => methodimpl.cs} (100%) rename src/tests/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/{non_virtual_calls_to_instance_methods.cs.template => non_virtual_calls_to_instance_methods.cs} (100%) rename src/tests/Loader/classloader/DefaultInterfaceMethods/sharedgenerics/{sharedgenerics.cs.template => sharedgenerics.cs} (100%) rename src/tests/Loader/classloader/DefaultInterfaceMethods/simple/{simple.cs.template => simple.cs} (100%) rename src/tests/Loader/classloader/DefaultInterfaceMethods/valuetypes/{valuetypes.cs.template => valuetypes.cs} (100%) delete mode 100644 src/tests/Loader/classloader/StaticVirtualMethods/RegressionTests/GitHub_70385.cs.template delete mode 100644 src/tests/Loader/classloader/StaticVirtualMethods/RegressionTests/GitHub_70385.il delete mode 100644 src/tests/Loader/classloader/StaticVirtualMethods/RegressionTests/GitHub_70385.ilproj delete mode 100644 src/tests/baseservices/exceptions/exceptioninterop/CMakeLists.txt delete mode 100644 src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.cs delete mode 100644 src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.csproj delete mode 100644 src/tests/baseservices/exceptions/exceptioninterop/ExceptionInteropNative.cpp delete mode 100644 src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop_ro.csproj delete mode 100644 src/tests/baseservices/invalid_operations/InvalidOperations.csproj delete mode 100644 src/tests/baseservices/invalid_operations/ManagedPointers.cs rename src/tests/nativeaot/SmokeTests/Reflection/{Reflection_FromUsage.csproj => Reflection_ReflectedOnly.csproj} (84%) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index da9f3bf10c05b..76d5359f980ba 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "1.0.0-prerelease.22320.3", + "version": "1.0.0-prerelease.22305.1", "commands": [ "xharness" ] diff --git a/Directory.Build.props b/Directory.Build.props index 4f9312803f030..45dabffc314c7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -35,7 +35,6 @@ arm64 loongarch64 s390x - ppc64le wasm x64 x64 diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index 83f7a5ab45da1..307da15465cec 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -1099,40 +1099,3 @@ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -License notice for code from The Practice of Programming -------------------------------- - -Copyright (C) 1999 Lucent Technologies - -Excerpted from 'The Practice of Programming -by Brian W. Kernighan and Rob Pike - -You may use this code for any purpose, as long as you leave the copyright notice and book citation attached. - -License notice for amd/aocl-libm-ose -------------------------------- - -Copyright (C) 2008-2020 Advanced Micro Devices, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. -3. Neither the name of the copyright holder nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/coding-guidelines/clr-code-guide.md b/docs/coding-guidelines/clr-code-guide.md index 88a4c3a06c74f..85987de5b047e 100644 --- a/docs/coding-guidelines/clr-code-guide.md +++ b/docs/coding-guidelines/clr-code-guide.md @@ -437,7 +437,7 @@ A GC_NOTRIGGER function cannot: [1] With one exception: GCX_COOP (which effects a preemp->coop->preemp roundtrip) is permitted. The rationale is that GCX_COOP becomes a NOP if the thread was cooperative to begin with so it's safe to allow this (and necessary to avoid some awkward code in our product.) -**Note that for GC to be truly prevented, the caller must also ensure that the thread is in cooperative mode.** Otherwise, all the precautions above are in vain since any other thread can start a GC at any time. Given that, you might be wondering why cooperative mode is not part of the definition of GC_NOTRIGGER. In fact, there is a third thread state called GC_FORBID which is exactly that: GC_NOTRIGGER plus forced cooperative mode. As its name implies, GC_FORBID _guarantees_ that no GC will occur on any thread. +**Note that for GC to be truly prevented, the caller must also ensure that the thread is in cooperative mode.** Otherwise, all the precautions above are in vain since any other thread can start a GC at any time. Given that, you might be wondering why cooperative mode is not part of the definition of GC_NOTRIGGER. In fact, there is a third thread state called GC_FORBID which is exactly that: GC_TRIGGERS plus forced cooperative mode. As its name implies, GC_FORBID _guarantees_ that no GC will occur on any thread. Why do we use GC_NOTRIGGERS rather than GC_FORBID? Because forcing every function to choose between GC_TRIGGERS and GC_FORBID is too inflexible given that some callers don't actually care about GC. Consider a simple class member function that returns the value of a field. How should it be declared? If you choose GC_TRIGGERS, then the function cannot be legally called from a GC_NOTRIGGER function even though this is perfectly safe. If you choose GC_FORBID, then every caller must switch to cooperative mode to invoke the function just to prevent an assert. Thus, GC_NOTRIGGER was created as a middle ground and has become far more pervasive and useful than GC_FORBID. Callers who actually need GC stopped will have put themselves in cooperative mode anyway and in those cases, GC_NOTRIGGER actually becomes GC_FORBID. Callers who don't care can just call the function and not worry about modes. diff --git a/docs/coding-guidelines/mono-code-guide.md b/docs/coding-guidelines/mono-code-guide.md deleted file mode 100644 index 8433df9f7b655..0000000000000 --- a/docs/coding-guidelines/mono-code-guide.md +++ /dev/null @@ -1,253 +0,0 @@ -# Mono code guidelines - -This document is meant to capture guidelines for contributing code to -the [src/mono/mono/](../../src/mono/mono), -[src/native/public/mono](../../src/native/public/mono) areas of the -dotnet/runtime repo. - -In general this guide does not apply to: - -1. Shared native code in [src/native](../../src/native) -2. The Mono-specific C# code in [src/mono](../../src/mono) in System.Private.CoreLib or elsewhere - -## Code style - -Mono is written in C. - -We follow the [Mono Coding guidelines](https://www.mono-project.com/community/contributing/coding-guidelines/) for the C code - in particular: - -* tabs, not spaces -* space between a function name and the open parenthesis -* braces on the same line as `if`, `for`, `while` etc - -## Naming - -Mono reserves the following prefixes for symbols: `mono_`, `monovm_`, `m_`, `monoeg_` (used to remap [`eglib`](../../src/mono/mono/eglib) -functions which in source code have a `g_` prefix). - -All non-`static` symbols should use one of these prefixes. We generally use `mono_` for most -functions. `m_` is used for some inline accessor functions and macros. `g_` (`mono_eg_`) is used -for `eglib` functions. - -Types in a single C file can use any name. Types in a header should use a `Mono` (or sometimes -`mono_`) prefix. - -Public API symbols and types *must* be prefixed. - -For types Mono generally uses `typedef struct _MonoWhatever { ... } MonoWhatever`. Opaque types may -define `typedef struct _MonoWhatever MonoWhatever` in a client header and define `struct -_MonoWhatever {...}` in an implementation header. Occasionally we break `#include` cycles by adding -forward declarations for some types. - -## Macros - -Mono derives from an autotools-style project so we generally write `HOST_XYZ` for the machine on -which the runtime is executing (as opposed to the machine on which the runtime was compiled), and -`TARGET_XYZ` for the machine that will be targeted by the JIT and AOT compilers. In the case of AOT -compilation host and target might be different: the host might be Windows, and the target might be -Browser WebAssembly, for example. - -Macros generally use a `MONO_` prefix. Macros in public API headers *must* use the prefix. - -## Types - -Prefer the standard C sized types `int32_t`, `intptr_t`, etc over the eglib types `gint32`, `gsize` etc. - -One exception is `gboolean` is prefered over C `bool`. - -There are actually three boolean types to keep in mind: - -* `gboolean` used internally in the runtime -* `MonoBoolean` used as an interop type with C# bool in internal calls -* `mono_bool` used by the public C API - generally new code shouldn't use it except when adding a new public API function. - -## Utility and platform abstraction functions - -Mono generally tries to fill in POSIX-like abstractions on platforms that lack them (for example, Windows). -This is in contrast to the CoreCLR PAL which generally tries to add Windows API abstractions on top -of POSIX. - -If an existing `eglib` utility function is available, it should be used. New ones can be added. - -Other platform specific code is in `src/mono/utils` - -## Directory dependencies - -For the code in `src/mono/mono`: - -* `eglib` should not depend on other code from `src/mono` - -* `utils` can depend on `eglib` and 3rd party code from `src/native/external` - -* `sgen` depends on `eglib` and `utils` - -* `metadata` depends on all of the above (but note that some Boehm-GC files in this directory should not depend on `sgen`) - -* `mini` depends on all of the above - -* `mini/interp` depends on all of the above - -* `components` can use functions from all of the above provided they're marked with - `MONO_COMPONENT_API`, see [../design/mono/components.md](../design/mono/components.md) - -The main distinction between `metadata` and `utils` is that utils code should not assume that it is -part of an executing .NET runtime - anything that loads types, creates objects, etc does not belong -in utils but in metadata. - -The `mini` directory contains execution engines. If the execution engine has to provide some -functionality to `metadata` it generally does so by installing some callback that is invoked by -`metadata`. For example, `mini` knows how to unwind exceptions and perform stack walks - while -`metadata` decides *when* to unwind or perform a stackwalk. To coordinate, `metadata` exposes an -API to install hooks and `mini` provides the implementations. - -## Error handling - -New code should prefer to use the `MonoError` functions. - -* A non-public-API function should take a `MonoError *` argument. -* In case of an error the function should call one of the `mono_error_set_` functions from [../../src/mono/mono/utils/mono-error-internals.h](../../src/mono/mono/utils/mono-error-internals.h) -* Inside the runtime check whether there was an error by calling `is_ok (error)`, `mono_error_assert_ok (error)`, `goto_if_nok` or `return_if_nok`/`return_val_if_nok` -* If there is an error and you're handling it, call `mono_error_cleanup (error)` to dispose of the resources. -* `MonoError*` is generally one-shot: after it's been cleaned up it needs to be re-inited with `mono_error_init_reuse`, but this is discouraged. -* Instead if you intend to deal with an error, use `ERROR_DECL (local_error)` then call the - possibly-failing function and pass it `local_error`, then call `mono_error_assert_ok - (local_error)` if it "can't fail" or `mono_error_cleanup (local_error)` if you want to ignore the - failure. - -## Managed Exceptions - -New code should generally not deal with `MonoException*`, use `MonoError*` instead. - -New code should avoid using `mono_error_set_pending_exception` - it affects a thread-local flag in -a way that is not obvious to the caller of your function and may trample existing in-flight -exceptions and make your code fail in unexpected ways. - -There are two circumstances when you might need to call `mono_error_set_pending_exception`: - -1. You're working with a public Mono API that sets a pending exception -2. You're implementing an icall, but can't use `HANDLES()` (see the [internal calls](#internal-calls) section below) - -## Internal calls - -Prefer P/Invokes or QCalls over internal calls. That is, if your function only takes arguments that -are not managed objects, and does not need to interact with the runtime, it is better to define it -outside the runtime. - -Internal calls generally have at least one argument that is a managed object, or may throw a managed exception. - -Internal calls are declared in [`icall-def.h`](../../src/mono/mono/metadata/icall-def.h) See the comment in the header for details. - -There are two styles of internal calls: `NOHANDLES` and `HANDLES`. (This is a simplification as there -are also JIT internal calls added by the execution engines) - -The difference is that `HANDLES` icalls receive references to managed objects wrapped in a handle -that attempts to keep the object alive for the duration of the internal call even if the thread -blocks or is suspended, while `NOHANDLES` functions don't. Additionally `HANDLES` functions get a -`MonoError*` argument from the managed-to-native interop layer that will be converted to a managed -exception when the function returns. `NOHANDLES` functions generally have to call -`mono_error_set_pending_exception` themselves. - -## Suspend Safety - -See [Cooperative Suspend at mono-project.com](https://www.mono-project.com/docs/advanced/runtime/docs/coop-suspend/) and the [mono thread state machine design document](../design/mono/mono-thread-state-machine.md) - -In general runtime functions that may be called from the public Mono API should call -`MONO_ENTER_GC_UNSAFE`/`MONO_EXIT_GC_UNSAFE` if they call any other runtime API. Internal calls are -already in GC Unsafe on entry, but QCalls and P/Invokes aren't. - -When calling a blocking native API, wrap the call in `MONO_ENTER_GC_SAFE`/`MONO_EXIT_GC_SAFE`. - -Prefer `mono_coop_` synchronization primitives (`MonoCoopMutex`, `MonoCoopCond`, -`MonoCoopSemaphore`, etc) over `mono_os_` primitives (`mono_mutex_t`, `mono_cond_t`). The former -will automatically go into GC Safe mode before doing operations that may block. The latter should -only be used for low-level leaf locks that may need to be shared with non-runtime code. You're -responsible for switching to GC Safe mode when doing blocking operations in that case. - -## GC Memory Safety - -We have explored many different policies on how to safely access managed memory from the runtime. The existing code is not uniform. - -This is the current policy (but check with a team member as this document may need to be updated): - -1. It is never ok to access a managed object from GC Safe code. -2. Mono's GC scans the managed heap precisely. Mono does not allow heap objects to contain pointers into the interior of other managed obejcts. -3. Mono's GC scans the native stack conservatively: any value that looks like a pointer into the GC - heap, will cause the target object to be pinned and not collected. Interior pointers from the - stack into the middle of a managed object are allowed and will pin the object. - -In general one of the following should be used to ensure that an object is kept alive, particularly -across a call back into managed from native, or across a call that may trigger a GC (effectively -nearly any runtime internal API, due to assembly loading potentially triggering managed callbacks): - -* The object is pinned in managed code using `fixed` (common with strings) and the native code gets a `gunichar2*` -* a `ref` local is passed into native code and the native code gets a `MonoObject * volatile *` (the `volatile` is important) -* a `Span` is passed into native code and the native code gets a `MonoSpanOfObjects*` -* an icall is declared with `HANDLES()` and a `MonoObjectHandle` (or a more specific type such as `MonoReflectionTypeHandle` is passed in). -* a GCHandle is passed in - -Generally only functions on the boundary between managed and native should use one of the above -mechanisms (that is, it's enough that an object is pinned once). Callees can take a `MonoObject*` -argument and assume that it was pinned by the caller. - -In cases where an object is created in native code, it should be kept alive: - -1. By assigning into a `MonoObject * volatile *` (ie: use `out` or `ref` arguments in C#) -2. By creating a local handle using `MONO_HANDLE_NEW` or `MONO_HANDLE_PIN` (the function should then use `HANDLE_FUNCTION_ENTER`/`HANDLE_FUNCTION_RETURN` to set up and tear down a handle frame) -3. By creating a GCHandle -4. By assigning to a field of another managed object - -In all cases, if there is any intervening internal API call or a call to managed code, the object -must be kept alive before the call using one of the above methods. - -### Write barriers - -When writing a managed object to a field of another managed object, use one of the -`mono_gc_wbarrier_` functions (for example, `mono_gc_wbarrier_generic_store`). It is ok to call the write -barrier functions if the destination is not in the managed heap (in which case they will just do a normal write) - -## Assertions - -Mono code should use `g_assert`, `mono_error_assert_ok`, `g_assertf`, `g_assert_not_reached` etc. - -Unlike CoreCLR, Mono assertions are always included in the runtime - both in Debug and in Release builds. - -New code should try not to rely on the side-effects of assert conditions. (That is, one day we may want -to turn off assertions in Release builds.) - -## Mono Public API - -Mono maintains a public API for projects that embed the Mono runtime in order to provide the ability -to execute .NET code in the context of another application or framework. The current Mono API is -`mono-2.0`. We strive to maintain binary ABI and API stability for our embedders. - -The public API headers are defined in -[`../../src/native/public/mono`](../../src/native/public/mono). Great care should be taken when -modifying any of the functions declared in these headers. In particular breaking the ABI by -removing these functions or changing their arguments is not allowed. Semantic changes should be -avoided, or implemented in a way that is least disruptive to embedders (for example the runtime does -not support multiple appdomains anymore, but `mono_domain_get` continues to work). - -### Hidden API functions - -In practice certain functions have been tagged with `MONO_API` even if they are not declared in the -public headers. These symbols have been used by projects that embed Mono despite not being in the -public headers. They should be treated with the same care as the real public API. - -### Unstable API functions - -Functions declared in `mono-private-unstable.h` headers do not need to maintain API/ABI stability. -They are generally new APIs that have been added since .NET 5 but that have not been stabilized yet. - -As a matter of courtesy, notify the .NET macios and .NET Android teams if changing the behavior of these functions. - -### WASM - -The WASM and WASI runtimes in [`src/mono/wasm/runtime`](../../src/mono/wasm/runtime) and -`src/mono/wasi` are effectively external API clients. When possible they should use existing `MONO_API` functions. - -As a matter of expedience, the wasm project has sometimes taken advantage of static linking by -adding declarations of internal Mono functions in `src/mono/wasm/runtime/driver.c` and directly -calling Mono internals. - -In general new code should not do this. When modifying existing code, mysterious WASM failures may -be attributed to symbol signature mismatches between WASM and the Mono runtime. diff --git a/docs/design/coreclr/botr/dac-notes.md b/docs/design/coreclr/botr/dac-notes.md index 64cc01fd935e0..099807e9d5583 100644 --- a/docs/design/coreclr/botr/dac-notes.md +++ b/docs/design/coreclr/botr/dac-notes.md @@ -15,7 +15,7 @@ The DAC infrastructure (the macros and templates that control how host or target When one has no understanding of the DAC, it's easy to find the use of the DAC infrastructure annoying. The `TADDR`s and `PTR_this` and `dac_casts`, etc. seem to clutter the code and make it harder to understand. With just a little work, though, you'll find that these are not really difficult to learn. Keeping host and target addresses explicitly different is really a form of strong typing. The more diligent we are, the easier it becomes to ensure our code is correct. -Because the DAC potentially operates on a dump, the part of the VM sources we build in mscordacwks.dll (msdaccore.dll) must be non-invasive. Specifically, we usually don't want to do anything that would cause writing to the target's address space, nor can we execute any code that might cause an immediate garbage collection. (If we can defer the GC, it may be possible to allocate.) Note that the _host_ state is always mutated (temporaries, stack or local heap values); it is only mutating the _target_ space that is problematic. To enforce this, we do two things: code factoring and conditional compilation. In an ideal world, we would factor the VM code so that we would strictly isolate invasive actions in functions that are separate from non-invasive functions. +Because the DAC potentially operates on a dump, the part of the VM sources we build in clr.dll (msdaccore.dll) must be non-invasive. Specifically, we usually don't want to do anything that would cause writing to the target's address space, nor can we execute any code that might cause an immediate garbage collection. (If we can defer the GC, it may be possible to allocate.) Note that the _host_ state is always mutated (temporaries, stack or local heap values); it is only mutating the _target_ space that is problematic. To enforce this, we do two things: code factoring and conditional compilation. In an ideal world, we would factor the VM code so that we would strictly isolate invasive actions in functions that are separate from non-invasive functions. Unfortunately, we have a large code base, most of which we wrote without ever thinking about the DAC at all. We have a significant number of functions with "find or create" semantics and many other functions that have some parts that just do inspection and other parts that write to the target. Sometimes we control this with a flag passed into the function. This is common in loader code, for example. To avoid having to complete the immense job of refactoring all the VM code before we can use the DAC, we have a second method to prevent executing invasive code from out of process. We have a defined pre-processor constant, `DACCESS_COMPILE` that we use to control what parts of the code we compile into the DAC. We would like to use the `DACCESS_COMPILE` constant as little as we can, so when we DACize a new code path, we prefer to refactor whenever possible. Thus, a function that has "find or create" semantics should become two functions: one that tries to find the information and a wrapper that calls this and creates if the find fails. That way, the DAC code path can call the find function directly and avoid the creation. diff --git a/docs/design/libraries/LibraryImportGenerator/Compatibility.md b/docs/design/libraries/LibraryImportGenerator/Compatibility.md index 27cf3fa45e0fd..0e3cd08727fb9 100644 --- a/docs/design/libraries/LibraryImportGenerator/Compatibility.md +++ b/docs/design/libraries/LibraryImportGenerator/Compatibility.md @@ -2,15 +2,6 @@ Documentation on compatibility guidance and the current state. The version headings act as a rolling delta between the previous version. -## Version 2 - -The focus of version 2 is to support all repos that make up the .NET Product, including ASP.NET Core and Windows Forms, as well as all packages in dotnet/runtime. - -### User defined type marshalling - -Support for user-defined type marshalling in the source-generated marshalling is described in [UserTypeMarshallingV2.md](UserTypeMarshallingV2.md). This support replaces the designs specified in [StructMarshalling.md](StructMarshalling.md) and [SpanMarshallers.md](SpanMarshallers.md). - - ## Version 1 The focus of version 1 is to support `NetCoreApp`. This implies that anything not needed by `NetCoreApp` is subject to change. diff --git a/docs/design/libraries/LibraryImportGenerator/Pipeline.md b/docs/design/libraries/LibraryImportGenerator/Pipeline.md index 9533241c9ad29..325da5e3edb8d 100644 --- a/docs/design/libraries/LibraryImportGenerator/Pipeline.md +++ b/docs/design/libraries/LibraryImportGenerator/Pipeline.md @@ -75,17 +75,11 @@ The stub code generator itself will handle some initial setup and variable decla 1. `Pin`: data pinning in preparation for calling the generated P/Invoke - Call `Generate` on the marshalling generator for every parameter - Ignore any statements that are not `fixed` statements -1. `PinnedMarshal`: conversion of managed to native data - - Call `Generate` on the marshalling generator for every parameter 1. `Invoke`: call to the generated P/Invoke - Call `AsArgument` on the marshalling generator for every parameter - Create invocation statement that calls the generated P/Invoke -1. `NotifyForSuccessfulInvoke`: Notify a marshaller that all stages through the "Invoke" stage were successful. - - Used to keep alive any objects who's native representation won't keep them alive across the call. +1. `KeepAlive`: keep alive any objects who's native representation won't keep them alive across the call. - Call `Generate` on the marshalling generator for every parameter. -1. `UnmarshalCapture`: capture any native out parameters to avoid memory leaks if exceptions are thrown during `Unmarshal`. - - If the method has a non-void return, call `Generate` on the marshalling generator for the return - - Call `Generate` on the marshalling generator for every parameter 1. `Unmarshal`: conversion of native to managed data - If the method has a non-void return, call `Generate` on the marshalling generator for the return - Call `Generate` on the marshalling generator for every parameter @@ -103,11 +97,9 @@ try << Marshal >> << Pin >> (fixed) { - << Pinned Marshal >> << Invoke >> } - << Notify For Successful Invoke >> - << Unmarshal Capture >> + << Keep Alive >> << Unmarshal >> } finally diff --git a/docs/design/libraries/LibraryImportGenerator/SpanMarshallers.md b/docs/design/libraries/LibraryImportGenerator/SpanMarshallers.md index d4dcae008de96..320c48a5d6574 100644 --- a/docs/design/libraries/LibraryImportGenerator/SpanMarshallers.md +++ b/docs/design/libraries/LibraryImportGenerator/SpanMarshallers.md @@ -2,8 +2,6 @@ As part of the exit criteria for the LibraryImportGenerator experiment, we have decided to introduce support for marshalling `System.Span` and `System.ReadOnlySpan` into the LibraryImportGenerator-generated stubs. This document describes design decisions made during the implementation of these marshallers. -> NOTE: These design docs are kept for historical purposes. The designs in this file are superseded by the designs in [UserTypeMarshallingV2.md](UserTypeMarshallingV2.md). - ## Design 1: "Intrinsic" support for `(ReadOnly)Span` In this design, the default support for `(ReadOnly)Span` is emitted into the marshalling stub directly and builds on the pattern we enabled for arrays. diff --git a/docs/design/libraries/LibraryImportGenerator/StructMarshalling.md b/docs/design/libraries/LibraryImportGenerator/StructMarshalling.md index 18fa309d3d3fe..c865ae2bae932 100644 --- a/docs/design/libraries/LibraryImportGenerator/StructMarshalling.md +++ b/docs/design/libraries/LibraryImportGenerator/StructMarshalling.md @@ -4,8 +4,6 @@ As part of the new source-generated direction for .NET Interop, we are looking a These types pose an interesting problem for a number of reasons listed below. With a few constraints, I believe we can create a system that will enable users to use their own user-defined types and pass them by-value to native code. -> NOTE: These design docs are kept for historical purposes. The designs in this file are superseded by the designs in [UserTypeMarshallingV2.md](UserTypeMarshallingV2.md). - ## Problems - What types require marshalling and what types can be passed as-is to native code? @@ -141,7 +139,7 @@ When these `CallerAllocatedBuffer` feature flag is present, the source generator Type authors can pass down the `buffer` pointer to native code by using the `TwoStageMarshalling` feature to provide a `ToNativeValue` method that returns a pointer to the first element, generally through code using `MemoryMarshal.GetReference()` and `Unsafe.AsPointer`. The `buffer` span must be pinned to be used safely. The `buffer` span can be pinned by defining a `GetPinnableReference()` method on the native type that returns a reference to the first element of the span. -### Determining if a type doesn't need marshalling +### Determining if a type is doesn't need marshalling For this design, we need to decide how to determine a type doesn't need to be marshalled and already has a representation we can pass directly to native code - that is, we need a definition for "does not require marshalling". We have two designs that we have experimented with below, and we have decided to go with design 2. diff --git a/docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md b/docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md deleted file mode 100644 index 072a97ab18ee5..0000000000000 --- a/docs/design/libraries/LibraryImportGenerator/UserTypeMarshallingV2.md +++ /dev/null @@ -1,768 +0,0 @@ -# User Defined Type Marshalling for Source-Generated Interop - -For the V1 of our source-generator, we designed support for marshalling collection types and user-defined structure types based on the designs in [StructMarshalling.md](StructMarshalling.md) and [SpanMarshallers.md](SpanMarshallers.md). As the model was adopted throughout dotnet/runtime, ASP.NET Core, WinForms, and early adopters, we recieved substantial feedback that led us to reconsider some components of the design. - -Here are some of the main feedback points on the previous design: - -- State diagram was complex - - The particular order in which methods are called on the marshallers were not simple to define. - - Handling exception scenarios without causing memory leaks was difficult. - - Supporting state preservation in "element of a collection" scenarios was going to be extremely difficult. -- Overcomplicated for simple marshallers - - The support for "Transparent Structures" in the original design added additional overhead on the base design instead of making this scenario cheaper. -- Concept Overload - - The design with optional features and multiple shapes was getting to the point that introducing people to the design was going to be difficult as there were many small options to pick. -- Limited specialization capabilities - - The V1 design mapped a single managed type to a single marshaller type. As a result, if the marshaller type required specialized support for a particular scenario such as a stack-allocated buffer optimization, then every scenario had to pay the overhead to support that conditional optimization. - - A marshaller could only be the marshaller for one managed type. As a result, if two types (such as `string` and `char`) both wanted to use the same marshalling concept, the developer would need to use two different marshaller types. - -The new design tries to address many of these concerns. - -The new marshallers have a stateless shape and a stateful shape. Stateful shapes are (currently) not allowed in "element of a collection" scenarios as handling them is difficult today, but we may improve this in the future. The stateful shapes are described in the order in which the methods will be called. Additionally, by moving away from using constructors for part of the marshalling, we can simplify the exception-handling guidance as we will only ever have one marshaller instance per parameter and it will always be assigned to the local. - -Stateless shapes avoid the problems of maintaining state and will be the primarily used shapes (they cover 90+% of our scenarios). - -The new stateless shapes provide simple mechanisms to implement marshalling for "Transparent Structures" without adding additional complexity. - -The new design has less "optional" members and each member in a shape is always used when provided. - -The new design uses a "marshaller entry-point" type to name a concept, which the user provides attributes on to point to the actual marshaller types per-scenario. This enables a marshaller entry-point type to provide specialized support for particular scenarios and support multiple managed types with one marshaller entry-point type. - -## API Diff for Supporting Attributes - -```diff -namespace System.Runtime.InteropServices.Marshalling; - -- [AttributeUsage(AttributeTargets.Struct)] -- public sealed class CustomTypeMarshallerAttribute : Attribute -- { -- public CustomTypeMarshallerAttribute(Type managedType, CustomTypeMarshallerKind marshallerKind = - CustomTypeMarshallerKind.Value) -- { -- ManagedType = managedType; -- MarshallerKind = marshallerKind; -- } -- -- public Type ManagedType { get; } -- public CustomTypeMarshallerKind MarshallerKind { get; } -- public int BufferSize { get; set; } -- public CustomTypeMarshallerDirection Direction { get; set; } = CustomTypeMarshallerDirection.Ref; -- public CustomTypeMarshallerFeatures Features { get; set; } -- public struct GenericPlaceholder -- { -- } -- } -- -- public enum CustomTypeMarshallerKind -- { -- Value, -- LinearCollection -- } -- -- [Flags] -- public enum CustomTypeMarshallerFeatures -- { -- None = 0, -- /// -- /// The marshaller owns unmanaged resources that must be freed -- /// -- UnmanagedResources = 0x1, -- /// -- /// The marshaller can use a caller-allocated buffer instead of allocating in some scenarios -- /// -- CallerAllocatedBuffer = 0x2, -- /// -- /// The marshaller uses the two-stage marshalling design for its instead of the - one-stage design. -- /// -- TwoStageMarshalling = 0x4 -- } -- [Flags] -- public enum CustomTypeMarshallerDirection -- { -- /// -- /// No marshalling direction -- /// -- [EditorBrowsable(EditorBrowsableState.Never)] -- None = 0, -- /// -- /// Marshalling from a managed environment to an unmanaged environment -- /// -- In = 0x1, -- /// -- /// Marshalling from an unmanaged environment to a managed environment -- /// -- Out = 0x2, -- /// -- /// Marshalling to and from managed and unmanaged environments -- /// -- Ref = In | Out, -- } - -+ /// -+ /// Define features for a custom type marshaller. -+ /// -+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] -+ public sealed class CustomTypeMarshallerFeaturesAttribute : Attribute -+ { -+ /// -+ /// Desired caller buffer size for the marshaller. -+ /// -+ public int BufferSize { get; set; } -+ } -+ -+ -+ /// -+ /// Base class attribute for custom marshaller attributes. -+ /// -+ /// -+ /// Use a base class here to allow doing ManagedToUnmanagedMarshallersAttribute.GenericPlaceholder, etc. without having 3 + separate placeholder types. -+ /// For the following attribute types, any marshaller types that are provided will be validated by an analyzer to have the + correct members to prevent -+ /// developers from accidentally typoing a member like Free() and causing memory leaks. -+ /// -+ public abstract class CustomUnmanagedTypeMarshallersAttributeBase : Attribute -+ { -+ /// -+ /// Placeholder type for generic parameter -+ /// -+ public sealed class GenericPlaceholder { } -+ } -+ -+ /// -+ /// Specify marshallers used in the managed to unmanaged direction (that is, P/Invoke) -+ /// -+ [AttributeUsage(AttributeTargets.Class)] -+ public sealed class ManagedToUnmanagedMarshallersAttribute : CustomUnmanagedTypeMarshallersAttributeBase -+ { -+ /// -+ /// Create instance of . -+ /// -+ /// Managed type to marshal -+ public ManagedToUnmanagedMarshallersAttribute(Type managedType) { } -+ -+ /// -+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the in keyword. -+ /// -+ public Type? InMarshaller { get; set; } -+ -+ /// -+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the ref keyword. -+ /// -+ public Type? RefMarshaller { get; set; } -+ -+ /// -+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the out keyword. -+ /// -+ public Type? OutMarshaller { get; set; } -+ } -+ -+ /// -+ /// Specify marshallers used in the unmanaged to managed direction (that is, Reverse P/Invoke) -+ /// -+ [AttributeUsage(AttributeTargets.Class)] -+ public sealed class UnmanagedToManagedMarshallersAttribute : CustomUnmanagedTypeMarshallersAttributeBase -+ { -+ /// -+ /// Create instance of . -+ /// -+ /// Managed type to marshal -+ public UnmanagedToManagedMarshallersAttribute(Type managedType) { } -+ -+ /// -+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the in keyword. -+ /// -+ public Type? InMarshaller { get; set; } -+ -+ /// -+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the ref keyword. -+ /// -+ public Type? RefMarshaller { get; set; } -+ -+ /// -+ /// Marshaller to use when a parameter of the managed type is passed by-value or with the out keyword. -+ /// -+ public Type? OutMarshaller { get; set; } -+ } -+ -+ /// -+ /// Specify marshaller for array-element marshalling and default struct field marshalling. -+ /// -+ [AttributeUsage(AttributeTargets.Class)] -+ public sealed class ElementMarshallerAttribute : CustomUnmanagedTypeMarshallersAttributeBase -+ { -+ /// -+ /// Create instance of . -+ /// -+ /// Managed type to marshal -+ /// Marshaller type to use for marshalling . -+ public ElementMarshallerAttribute(Type managedType, Type elementMarshaller) { } -+ } -+ -+ /// -+ /// Specifies that a particular generic parameter is the collection element's unmanaged type. -+ /// -+ /// -+ /// If this attribute is provided on a generic parameter of a marshaller, then the generator will assume -+ /// that it is a linear collection marshaller. -+ /// -+ [AttributeUsage(AttributeTargets.GenericParameter)] -+ public sealed class ElementUnmanagedTypeAttribute : Attribute -+ { -+ } -``` - -## Design Details - -First of all, this new design continues to use the existing policy for defining "blittable" types as described in the V1 design. The rest of this document will describe the custom user-defined marshalling rules. - -In the new design, the user will first define an "entry-point type" that represents a marshalling concept. For example, if we are marshalling a `string` to a native UTF-8 encoded string, we might call the marshaller `Utf8StringMarshaller`. This new type will be a `static class`. The developer will then use the `ManagedToUnmanagedMarshallersAttribute`, `UnmanagedToManagedMarshallersAttribute`, and `ElementMarshallerAttribute` to specify which "marshaller implementation type" will be used to actually provide the marshalling. If an attribute is missing or a property on the attribute is set to `null` or left unset, this marshaller will not support marshalling in that scenario. A single type can be specified multiple times if it provides the marshalling support for multiple scenarios. - -To avoid confusion around when each marshaller applies, we define when the marshallers apply based on the C# syntax used. This helps reduce the concept load as developers don't need to remember the mapping between the previous design's `CustomTypeMarshallerDirection` enum member and the C# keyword used for a parameter, which do not match in a Reverse P/Invoke-like scenario. - -We will recommend that the marshaller types that are supplied are nested types of the "entry-point type" or the "entry-point type" itself, but we will not require it. Each specified marshaller type will have to abide by one of the following shapes depending on the scenario is supports. - -The examples below will also show which properties in each attribute support each marshaller shape. - -## Value Marshaller Shapes - -We'll start with the value marshaller shapes. These marshaller shapes support marshalling a single value. - -Each of these shapes will support marshalling the following type: - -```csharp -// Any number of generic parameters is allowed, with any constraints -struct TManaged -{ - // ... -} -``` - -The type `TNative` can be any `unmanaged` type. It represents whatever unmanaged type the marshaller marshals the managed type to. - -### Stateless Managed->Unmanaged - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller -{ - public static class ManagedToNative - { - public static TNative ConvertToUnmanaged(TManaged managed); // Can throw exceptions - - public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke. - - public static void Free(TNative unmanaged); // Optional. Should not throw exceptions - } -} - -``` -### Stateless Managed->Unmanaged with Caller-Allocated Buffer - -The element type of the `Span` for the caller-allocated buffer can be any type that guarantees any alignment requirements. - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller -{ - [CustomTypeMarshallerFeatures(BufferSize = 0x200)] - public static class ManagedToNative - { - public static TNative ConvertToUnmanaged(TManaged managed, Span callerAllocatedBuffer); // Can throw exceptions - - public static void Free(TNative unmanaged); // Optional. Should not throw exceptions - } -} - -``` - -### Stateless Unmanaged->Managed - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller -{ - public static class NativeToManaged - { - public static TManaged ConvertToManaged(TNative unmanaged); // Can throw exceptions - - public static void Free(TNative unmanaged); // Optional. Should not throw exceptions - } -} - -``` - -### Stateless Unmanaged->Managed with Guaranteed Unmarshalling - -This shape directs the generator to emit the `ConvertToManagedGuaranteed` call in the "GuaranteedUnmarshal" phase of marshalling. - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller -{ - public static class NativeToManaged - { - public static TManaged ConvertToManagedGuaranteed(TNative unmanaged); // Should not throw exceptions - - public static void Free(TNative unmanaged); // Optional. Should not throw exceptions - } -} - -``` - -### Stateless Bidirectional -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), RefMarshaller = typeof(Bidirectional))] -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), RefMarshaller = typeof(Bidirectional))] -[ElementMarshaller(typeof(TManaged<,,,...>), typeof(Bidirectional))] -static class TMarshaller -{ - public static class Bidirectional - { - // Include members from each of the following: - // - One Stateless Managed->Unmanaged Value shape - // - One Stateless Unmanaged->Managed Value shape - } -} - -``` - -### Stateful Managed->Unmanaged - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller -{ - public struct ManagedToNative // Can be ref struct - { - public ManagedToNative(); // Optional, can throw exceptions. - - public void FromManaged(TManaged managed); // Can throw exceptions. - - public ref TIgnored GetPinnableReference(); // Result pinned for ToUnmanaged call and Invoke, but not used otherwise. - - public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke. - - public TNative ToUnmanaged(); // Can throw exceptions. - - public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions. - - public void Free(); // Should not throw exceptions. - } -} - -``` -### Stateful Managed->Unmanaged with Caller Allocated Buffer - -The element type of the `Span` for the caller-allocated buffer can be any type that guarantees any alignment requirements. - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller -{ - [CustomTypeMarshallerFeatures(BufferSize = 0x200)] - public struct ManagedToNative // Can be ref struct - { - public ManagedToNative(); // Optional, can throw exceptions. - - public void FromManaged(TManaged managed, Span buffer); // Can throw exceptions. - - public ref TIgnored GetPinnableReference(); // Result pinned for ToUnmanaged call and Invoke, but not used otherwise. - - public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke. - - public TNative ToUnmanaged(); // Can throw exceptions. - - public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions. - - public void Free(); // Should not throw exceptions. - } -} - -``` - -### Stateful Unmanaged->Managed - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller -{ - public struct NativeToManaged // Can be ref struct - { - public NativeToManaged(); // Optional, can throw exceptions. - - public void FromUnmanaged(TNative native); // Should not throw exceptions. - - public TManaged ToManaged(); // Can throw exceptions. - - public void Free(); // Should not throw exceptions. - } -} - -``` - -### Stateful Unmanaged->Managed with Guaranteed Unmarshalling - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TManaged<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller -{ - public struct NativeToManaged // Can be ref struct - { - public NativeToManaged(); // Optional, can throw exceptions. - - public void FromUnmanaged(TNative native); // Should not throw exceptions. - - public TManaged ToManagedGuaranteed(); // Should not throw exceptions. - - public void Free(); // Should not throw exceptions. - } -} - -``` - -### Stateful Bidirectional -```csharp -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), RefMarshaller = typeof(Bidirectional))] -[ManagedToUnmanagedMarshallers(typeof(TManaged<,,,...>), RefMarshaller = typeof(Bidirectional))] -static class TMarshaller -{ - public struct Bidirectional // Can be ref struct - { - // Include members from each of the following: - // - One Stateful Managed->Unmanaged Value shape - // - One Stateful Unmanaged->Managed Value shape - } -} -``` - -## Linear (Array-like) Collection Marshaller Shapes - -We'll continue with the collection marshaller shapes. These marshaller shapes support marshalling the structure of a collection of values, where the values themselves are marshalled with marshallers of their own (using the marshaller provided in the `ElementMarshallerAttribute`). This construction allows us to compose our marshallers and to easily support arrays of custom types without needing to implement a separate marshaller for each element type. - -Each of these shapes will support marshalling the following type: - -```csharp -// Any number of generic parameters is allowed, with any constraints -struct TCollection -{ - // ... -} -``` - -A collection marshaller for a managed type will have similar generics handling as the value marshaller case; however, there is one difference. A collection marshaller must have an additional generic parameter with the `ElementUnmanagedTypeAttribute`. This parameter can optionally be constrained to `: unmanaged` (but the system will not require this). The attributed parameter will be filled in with a generics-compatible representation of the unmanaged type for the collection's element type (`nint` will be used when the native type is a pointer type). - -The type `TNative` can be any `unmanaged` type. It represents whatever unmanaged type the marshaller marshals the managed type to. - - -### Stateless Managed->Unmanaged - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public static class ManagedToNative - { - public static TNative AllocateContainerForUnmanagedElements(TCollection managed, out int numElements); // Can throw exceptions - - public static ReadOnlySpan GetManagedValuesSource(TCollection managed); // Can throw exceptions - - public static Span GetUnmanagedValuesDestination(TNative nativeValue, int numElements); // Can throw exceptions - - public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke. - - public static void Free(TNative unmanaged); // Optional. Should not throw exceptions - } -} - -``` -### Stateless Managed->Unmanaged with Caller-Allocated Buffer - -The element type of the `Span` for the caller-allocated buffer can be any type that guarantees any alignment requirements, including `TUnmanagedElement`. - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - [CustomTypeMarshallerFeatures(BufferSize = 0x200)] - public static class ManagedToNative - { - public static TNative AllocateContainerForUnmanagedElements(TCollection managed, Span buffer, out int numElements); // Can throw exceptions - - public static ReadOnlySpan GetManagedValuesSource(TCollection managed); // Can throw exceptions - - public static Span GetUnmanagedValuesDestination(TNative nativeValue, int numElements); // Can throw exceptions - - public static ref TOther GetPinnableReference(TManaged managed); // Optional. Can throw exceptions. Result pinnned and passed to Invoke. - - public static void Free(TNative unmanaged); // Optional. Should not throw exceptions - } -} - -``` - -### Stateless Unmanaged->Managed - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public static class NativeToManaged - { - public static TCollection AllocateContainerForManagedElements(int length); // Can throw exceptions - - public static Span GetManagedValuesDestination(T[] managed) => managed; // Can throw exceptions - - public static ReadOnlySpan GetUnmanagedValuesSource(TNative nativeValue, int numElements); // Can throw exceptions - - public static void Free(TNative native); // Optional. Should not throw exceptions. - } -} - -``` - -### Stateless Unmanaged->Managed with Guaranteed Unmarshalling - -This shape directs the generator to emit the `ConvertToManagedGuaranteed` call in the "GuaranteedUnmarshal" phase of marshalling. - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public static class NativeToManaged - { - public static TCollection AllocateContainerForManagedElementsGuaranteed(int length); // Should not throw exceptions other than OutOfMemoryException. - - public static Span GetManagedValuesDestination(T[] managed) => managed; // Can throw exceptions - - public static ReadOnlySpan GetUnmanagedValuesSource(TNative nativeValue, int numElements); // Can throw exceptions - - public static void Free(TNative native); // Optional. Should not throw exceptions. - } -} - -``` - -### Stateless Bidirectional -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))] -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))] -[ElementMarshaller(typeof(TManaged<,,,...>), typeof(Bidirectional))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public static class Bidirectional - { - // Include members from each of the following: - // - One Stateless Managed->Unmanaged Linear Collection shape - // - One Stateless Unmanaged->Managed Linear Collection shape - } -} - -``` - -### Stateful Managed->Unmanaged - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public struct ManagedToNative // Can be ref struct - { - public ManagedToNative(); // Optional, can throw exceptions. - - public void FromManaged(TCollection collection); // Can throw exceptions. - - public ReadOnlySpan GetManagedValuesSource(); // Can throw exceptions. - - public Span GetNativeValuesDestination(); // Can throw exceptions. - - public ref TIgnored GetPinnableReference(); // Optional. Can throw exceptions. - - public TNative ToUnmanaged(); // Can throw exceptions. - - public static ref TOther GetPinnableReference(TCollection collection); // Optional. Can throw exceptions. Result pinnned and passed to Invoke. - - public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions. - } -} - -``` -### Stateful Managed->Unmanaged with Caller Allocated Buffer - -The element type of the `Span` for the caller-allocated buffer can be any type that guarantees any alignment requirements. - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(ManagedToNative))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(ManagedToNative))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - [CustomTypeMarshallerFeatures(BufferSize = 0x200)] - public struct ManagedToNative // Can be ref struct - { - public ManagedToNative(); // Optional, can throw exceptions. - - public void FromManaged(TCollection collection, Span buffer); // Can throw exceptions. - - public ReadOnlySpan GetManagedValuesSource(); // Can throw exceptions. - - public Span GetNativeValuesDestination(); // Can throw exceptions. - - public ref TIgnored GetPinnableReference(); // Optional. Can throw exceptions. - - public TNative ToUnmanaged(); // Can throw exceptions. - - public static ref TOther GetPinnableReference(TCollection collection); // Optional. Can throw exceptions. Result pinnned and passed to Invoke. - - public void NotifyInvokeSucceeded(); // Optional. Should not throw exceptions. - } -} - -``` - -### Stateful Unmanaged->Managed - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public struct NativeToManaged // Can be ref struct - { - public NativeToManaged(); // Optional, can throw exceptions. - - public void FromUnmanaged(TNative value); // Should not throw exceptions. - - public ReadOnlySpan GetNativeValuesSource(int length); // Can throw exceptions. - - public Span GetManagedValuesDestination(int length); // Can throw exceptions. - - public TCollection ToManaged(); // Can throw exceptions - - public void Free(); // Optional. Should not throw exceptions. - } -} - -``` - -### Stateful Unmanaged->Managed with Guaranteed Unmarshalling - -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), OutMarshaller = typeof(NativeToManaged))] -[UnmanagedToManagedMarshallers(typeof(TCollection<,,,...>), InMarshaller = typeof(NativeToManaged))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public struct NativeToManaged // Can be ref struct - { - public NativeToManaged(); // Optional, can throw exceptions. - - public void FromUnmanaged(TNative value); // Should not throw exceptions. - - public ReadOnlySpan GetNativeValuesSource(int length); // Can throw exceptions. - - public Span GetManagedValuesDestination(int length); // Can throw exceptions. - - public TCollection ToManagedGuaranteed(); // Can throw exceptions - - public void Free(); // Optional. Should not throw exceptions. - } -} - -``` - -### Stateful Bidirectional -```csharp -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))] -[ManagedToUnmanagedMarshallers(typeof(TCollection<,,,...>), RefMarshaller = typeof(Bidirectional))] -static class TMarshaller where TUnmanagedElement : unmanaged -{ - public struct Bidirectional // Can be ref struct - { - // Include members from each of the following: - // - One Stateful Managed->Unmanaged Linear Collection shape - // - One Stateful Unmanaged->Managed Linear Collection shape - } -} -``` - -## Optional Members In Shapes - -There's a few optional members in the above shapes. This section explains what these members do and why they're optional. - -### Free method - -The `Free` method on each shape supports releasing any unmanaged (or managed in the stateful shapes) resources. This method is optional as the `Free` method is required to be called in a `finally` clause and emitting a `try-finally` block with only method calls to empty methods puts a lot of stress on the JIT to inline all of the methods and realize that they are no-ops to remove the `finally` clause. Additionally, just having the `try-finally` block wrapping the main code can cause some de-optimizations. - -### NotifyInvokeSucceeded method - -This method is called after a stub successfully invokes the target code (unmanaged code in a P/Invoke scenario, managed code in a Reverse P/Invoke scenario). As this method would be called in a very large majority of cases in P/Invoke-style scenarios and has only limited utility (its main use is to provide a good place to call `GC.KeepAlive` that does not require a `try-finally` block), we decided to make it optional. - -### Instance GetPinnableReference method on stateful shapes - -The non-static `GetPinnableReference` method on stateful shapes is provided to enable pinning a managed value as part of the marshalling process. As some types don't have values that need to be pinned to help with marshalling and pinning has some overhead, this member is optional to make the overhead pay-for-play. - -### Static GetPinnableReference method - -The static GetPinnableReference method provides a mechanism to pin a managed value and pass down the pinned value directly to native code. This allows us to provide massive performance benefits and to match built-in interop semantics. Unlike the previous design that used the `GetPinnableReference` method on the managed type in some scenarios, this design allows the "interop" pinning rules to not match the easier-to-use `GetPinnableReference` instance method, which may have differing semantics (`Span` and arrays being a prime example here). As many types aren't marshallable via only pinning, the generator does not require this method on every marshaller. - -### `-Generated` method variants - -These method variants provide a mechanism for a marshaller to state that it needs to be called during the "Generated Unmarshal" phase in the `finally` block to ensure that resources are not leaked. This feature is required only by the SafeHandle marshaller, so it is an optional extension to the model instead of being a required feature. - -## Blittability - -To determine which types are blittable and which are not, we will be following [Design 2 in StructMarshalling.md](StructMarshalling.md#determining-if-a-type-doesnt-need-marshalling). - -## Using the marshallers - -To use these marshallers the user would apply either the `NativeMarshallingAttribute` attribute to their type or a `MarshalUsingAttribute` at the marshalling location (field, parameter, or return value) with a marshalling type matching the same requirements as `NativeMarshallingAttribute`'s marshalling type. - -The marshaller type must be an entry-point marshaller type as defined above and meet the following additional requirements: - -- The type must either be: - - Non-generic - - A closed generic - - An open generic with as many generic parameters with compatible constraints as the managed type (excluding up to one generic parameter with the `ElementUnmanagedTypeAttribute`) -- If used in `NativeMarshallingAttribute`, the type should be at least as visible as the managed type. - -Passing size info for parameters will be based to the [V1 design](SpanMarshallers.md#providing-additional-data-for-collection-marshalling) and the properties/fields on `MarshalUsingAttribute` will remain unchanged. - -Here are some examples of using these new marshaller shapes with the `NativeMarshallingAttribute` and the `MarshalUsingAttribute`. - -```csharp -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; - -[NativeMarshalling(typeof(HResultMarshaller))] -struct HResult -{ - private int hr; -} - -[ManagedToUnmanagedMarshallers(typeof(HResult), InMarshaller = typeof(HResultMarshaller), RefMarshaller = typeof(HResultMarshaller), OutMarshaller = typeof(HResultMarshaller))] -[UnmanagedToManagedMarshallers(typeof(HResult), InMarshaller = typeof(HResultMarshaller), RefMarshaller = typeof(HResultMarshaller), OutMarshaller = typeof(HResultMarshaller))] -[ElementMarshaller(typeof(HResult), typeof(HResultMarshaller))] -public static class HResultMarshaller -{ - public static int ConvertToUnmanaged(HResult hr); - public static HResult ConvertToManaged(int hr); -} - -public static class NativeLib -{ - [LibraryImport(nameof(NativeLib))] - public static partial HResult CountArrayElements( - [MarshalUsing(typeof(ArrayMarshaller<,>))] int[] array, // Unlike the V1 system, we'll allow open generics in the V2 system in MarshalUsing since there's an extra generic parameter that the user does not provide. - out int numElements); -} - -``` diff --git a/docs/design/security/unix-tmp.md b/docs/design/security/unix-tmp.md deleted file mode 100644 index bea8cb8f11ae6..0000000000000 --- a/docs/design/security/unix-tmp.md +++ /dev/null @@ -1,45 +0,0 @@ - -# Unix temporary files - -The Unix support for temporary files is different from the Windows model and developers who -are used to Windows may inadvertently create security risk if they use the same practices on Unix. - -Most notably, the Windows model for temporary files is that the operating system provides each user with a *unique*, *user-owned* temporary directory. -Moreover, all Windows users, including the service and system users, have designated user folders, including temporary folders. - -The Unix model is very different. The temp directory, assuming there is one, is often a global folder (except on MacOS). -If possible, prefer a library function like `GetTempPath()` to find the folder. Otherwise, -the `TMPDIR` environment variable is used to store the location of this folder. This variable is -widely used and supported, but it is not mandatory for all Unix implementations. It should be the preferred -mechanism for finding the Unix temporary folder if a library method is not available. It will commonly -point to either the `/tmp` or `/var/tmp` folder. These folders are not used for MacOS, so it is not recommended -to use them directly. - -Because the temporary directory is often global, any use of the temp directory should be carefully -considered. In general, the best use of the temp directory is for programs which, - -1. Will create the temporary file during their process execution -1. Do not depend on predictable temporary file/folder names -1. Will not access the file after the process exits - -In these cases, the process can create a file or files with - 1. A pseudorandom name, unlikely to cause collisions - 1. Permissions which restrict all access to owner-only, i.e. 700 for directories, 600 for files - -Any other use needs to be carefully audited, particularly if the temporary file is intended for use across -multiple processes. Some considerations: - -- **Never** write files with global access permissions -- **Always** verify that the owner of the file is the current user and that the permissions - only allow write access by the owner when reading existing files -- **Never** rely on having ownership of a particular file name. Any process can write a file with that name, - creating a denial of service. - - When creating files, consider likelihood of file name collision and performance impact of attempting - to create new names, if supported. - - If any of the above conflict with the feature requirements, consider instead writing temporary files to a - location in the user home folder. Some considerations for this model: - - - There is no automatic cleanup in user folders. Files will remain permanently or require cleanup by the app - - Some environments do not have user home folders (e.g., systemd). Consider providing an environment variable - to override the location of the temporary folder, and provide user documentation for this variable. diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 876d4a62f58aa..c0e56c9fa04cf 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -17,7 +17,6 @@ This is a list of additions and edits to be made in ECMA-335 specifications. It - [Rules for IL rewriters](#rules-for-il-rewriters) - [Checked user-defined operators](#checked-user-defined-operators) - [Atomic reads and writes](#atomic-reads-and-writes) -- [Backward branch constraints](#backward-branch-constraints) ## Signatures @@ -1021,7 +1020,3 @@ A checked user-defined operator is expected to throw an exception when the resul Section "I.12.6.6 Atomic reads and writes" adds clarification that the atomicity guarantees apply to built-in primitive value types and pointers only. A conforming CLI shall guarantee that read and write access of *built-in primitive value types and pointers* to properly aligned memory locations no larger than the native word size (the size of type native int) is atomic (see §I.12.6.2) when all the write accesses to a location are the same size. - -## Backward branch constraints - -Section "II.1.7.5 Backward branch constraints" is deleted. These constraints were not enforced by any mainstream .NET runtime and they are not respected by .NET compilers. It means that it is not possible to infer the exact state of the evaluation stack at every instruction with a single forward-pass through the CIL instruction stream. diff --git a/docs/project/dogfooding.md b/docs/project/dogfooding.md index 69f405a7f8076..3ff4160095b1e 100644 --- a/docs/project/dogfooding.md +++ b/docs/project/dogfooding.md @@ -19,9 +19,9 @@ dotnet nuget add source -n dotnet7 https://dnceng.pkgs.visualstudio.com/public/_ Then, you will be able to add the latest prerelease version of the desired package to your project. -**Example:** To add version 7.0-preview.5.22226.4 of the System.Data.OleDb package, use the [dotnet add package](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package) command: +**Example:** To add version 7.0.100-preview.5.22226.4 of the System.Data.OleDb package, use the [dotnet add package](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package) command: ``` -dotnet add package System.Data.OleDb -v 7.0-preview.5.22226.4 +dotnet add package System.Data.OleDb -v 7.0.100-preview.5.22226.4 ``` To use nightly builds of the entire runtime, follow the steps given in the rest of this document instead. @@ -30,7 +30,9 @@ To use nightly builds of the entire runtime, follow the steps given in the rest 1. Acquire the latest nightly .NET SDK by downloading and extracting a zip/tarball or using an installer from the [installers and binaries table in dotnet/installer](https://github.com/dotnet/installer#installers-and-binaries) (for example, https://aka.ms/dotnet/7.0/daily/dotnet-sdk-win-x64.zip). -2. If you are using a local copy of the dotnet CLI, take care that when you type `dotnet` you do not inadvertently pick up a different copy that you may have in your path. On Windows, for example, if you use a Command Prompt, a global copy may be in the path, so use the fully qualified path to your local `dotnet` (e.g. `C:\dotnet\dotnet.exe`). If you receive an error "error NETSDK1045: The current .NET SDK does not support targeting .NET 7.0." then you may be executing an older `dotnet`. +2. By default, the dotnet CLI will use the globally installed SDK if it matches the major/minor version you request and has a higher revision. To force it to use a locally installed SDK, you must set an environment variable `DOTNET_MULTILEVEL_LOOKUP=0` in your shell. You can use `dotnet --info` to verify what version of the Shared Framework it is using. + +3. Reminder: if you are using a local copy of the dotnet CLI, take care that when you type `dotnet` you do not inadvertently pick up a different copy that you may have in your path. On Windows, for example, if you use a Command Prompt, a global copy may be in the path, so use the fully qualified path to your local `dotnet` (e.g. `C:\dotnet\dotnet.exe`). If you receive an error "error NETSDK1045: The current .NET SDK does not support targeting .NET 7.0." then you may be executing an older `dotnet`. After setting up dotnet you can verify you are using the dogfooding version by executing `dotnet --info`. Here is an example output at the time of writing: ``` @@ -68,10 +70,11 @@ Learn about .NET Runtimes and SDKs: ``` -3. Our nightly builds are uploaded to nightly feed, not NuGet - so ensure the nightly feed is in your nuget configuration in case you need other packages that aren't included in the download. For example, on Windows you could edit `%userprofile%\appdata\roaming\nuget\nuget.config` or on Linux edit `~/.nuget/NuGet/NuGet.Config` to add these lines: +4. Our nightly builds are uploaded to dotnet-blob feeds, not NuGet - so ensure the .NET Core blob feed is in your nuget configuration in case you need other packages from .NET Core that aren't included in the download. For example, on Windows you could edit `%userprofile%\appdata\roaming\nuget\nuget.config` or on Linux edit `~/.nuget/NuGet/NuGet.Config` to add these lines: ```xml - + + ... ``` @@ -142,7 +145,7 @@ make it self-contained by adding a RuntimeIdentifier (RID). net7.0 - + 7.0.0-preview.5.22224.3 win-x64 diff --git a/eng/CodeAnalysis.src.globalconfig b/eng/CodeAnalysis.src.globalconfig index 95f58b409563a..a9a8f29956cd2 100644 --- a/eng/CodeAnalysis.src.globalconfig +++ b/eng/CodeAnalysis.src.globalconfig @@ -411,9 +411,6 @@ dotnet_diagnostic.CA1852.severity = warning # CA1853: Unnecessary call to 'Dictionary.ContainsKey(key)' dotnet_diagnostic.CA1853.severity = warning -# CA1854: Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method -dotnet_diagnostic.CA1854.severity = warning - # CA2000: Dispose objects before losing scope dotnet_diagnostic.CA2000.severity = none @@ -1073,8 +1070,8 @@ dotnet_diagnostic.SA1204.severity = none # SA1205: Partial elements should declare an access modifier dotnet_diagnostic.SA1205.severity = warning -# SA1206: Keyword ordering - TODO Re-enable as warning after https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3527 -dotnet_diagnostic.SA1206.severity = suggestion +# SA1206: Keyword ordering +dotnet_diagnostic.SA1206.severity = warning # SA1208: Using directive ordering dotnet_diagnostic.SA1208.severity = none @@ -1356,7 +1353,7 @@ dotnet_diagnostic.IDE0018.severity = suggestion dotnet_diagnostic.IDE0019.severity = suggestion # IDE0020: Use pattern matching to avoid is check followed by a cast (with variable) -dotnet_diagnostic.IDE0020.severity = warning +dotnet_diagnostic.IDE0020.severity = suggestion # IDE0021: Use expression body for constructors dotnet_diagnostic.IDE0021.severity = silent @@ -1383,13 +1380,13 @@ dotnet_diagnostic.IDE0027.severity = silent dotnet_diagnostic.IDE0028.severity = suggestion # IDE0029: Use coalesce expression -dotnet_diagnostic.IDE0029.severity = warning +dotnet_diagnostic.IDE0029.severity = suggestion # IDE0030: Use coalesce expression -dotnet_diagnostic.IDE0030.severity = warning +dotnet_diagnostic.IDE0030.severity = suggestion # IDE0031: Use null propagation -dotnet_diagnostic.IDE0031.severity = warning +dotnet_diagnostic.IDE0031.severity = silent # IDE0032: Use auto property dotnet_diagnostic.IDE0032.severity = silent @@ -1404,7 +1401,7 @@ dotnet_diagnostic.IDE0034.severity = suggestion dotnet_diagnostic.IDE0035.severity = suggestion # IDE0036: Order modifiers -dotnet_diagnostic.IDE0036.severity = warning +dotnet_diagnostic.IDE0036.severity = suggestion # IDE0037: Use inferred member name dotnet_diagnostic.IDE0037.severity = silent @@ -1458,7 +1455,7 @@ dotnet_diagnostic.IDE0052.severity = suggestion dotnet_diagnostic.IDE0053.severity = silent # IDE0054: Use compound assignment -dotnet_diagnostic.IDE0054.severity = warning +dotnet_diagnostic.IDE0054.severity = suggestion # IDE0055: Fix formatting dotnet_diagnostic.IDE0055.severity = suggestion @@ -1492,7 +1489,7 @@ dotnet_diagnostic.IDE0063.severity = silent dotnet_diagnostic.IDE0064.severity = silent # IDE0065: Misplaced using directive -dotnet_diagnostic.IDE0065.severity = warning +dotnet_diagnostic.IDE0065.severity = suggestion # IDE0066: Convert switch statement to expression dotnet_diagnostic.IDE0066.severity = suggestion @@ -1501,7 +1498,7 @@ dotnet_diagnostic.IDE0066.severity = suggestion dotnet_diagnostic.IDE0070.severity = suggestion # IDE0071: Simplify interpolation -dotnet_diagnostic.IDE0071.severity = warning +dotnet_diagnostic.IDE0071.severity = suggestion # IDE0072: Add missing cases dotnet_diagnostic.IDE0072.severity = silent @@ -1546,10 +1543,10 @@ dotnet_diagnostic.IDE0084.severity = none dotnet_diagnostic.IDE0090.severity = silent # IDE0100: Remove redundant equality -dotnet_diagnostic.IDE0100.severity = warning +dotnet_diagnostic.IDE0100.severity = suggestion # IDE0110: Remove unnecessary discard -dotnet_diagnostic.IDE0110.severity = warning +dotnet_diagnostic.IDE0110.severity = suggestion # IDE0120: Simplify LINQ expression dotnet_diagnostic.IDE0120.severity = none @@ -1570,7 +1567,7 @@ dotnet_diagnostic.IDE0160.severity = silent dotnet_diagnostic.IDE0161.severity = silent # IDE1005: Delegate invocation can be simplified. -dotnet_diagnostic.IDE1005.severity = warning +dotnet_diagnostic.IDE1005.severity = suggestion # IDE1006: Naming styles dotnet_diagnostic.IDE1006.severity = silent diff --git a/eng/CodeAnalysis.test.globalconfig b/eng/CodeAnalysis.test.globalconfig index 59fc4e0022deb..97bf6113e88e7 100644 --- a/eng/CodeAnalysis.test.globalconfig +++ b/eng/CodeAnalysis.test.globalconfig @@ -408,9 +408,6 @@ dotnet_diagnostic.CA1852.severity = none # CA1853: Unnecessary call to 'Dictionary.ContainsKey(key)' dotnet_diagnostic.CA1853.severity = none -# CA1854: Prefer the 'IDictionary.TryGetValue(TKey, out TValue)' method -dotnet_diagnostic.CA1854.severity = none - # CA2000: Dispose objects before losing scope dotnet_diagnostic.CA2000.severity = none diff --git a/eng/Subsets.props b/eng/Subsets.props index 1d08c11b1013a..4fbd6b5e3fbf6 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -27,7 +27,7 @@ flavor is used to decide when to build the hosts and installers. --> CoreCLR - Mono + Mono @@ -312,8 +312,6 @@ Test="true" Category="clr" Condition="'$(DotNetBuildFromSource)' != 'true'"/> - diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index d7a0af994c93e..df1d92585c1e8 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,16 +1,16 @@ - + https://github.com/dotnet/icu - 8ea608427e5988d3dd25130400947aad0a917bba + 7c13e1a1740e54ba0c9b38636ae36195c9e9d3bd https://github.com/dotnet/msquic b4d67ca60d3f819e2450095ab8a33a9f65513e4a - + https://github.com/dotnet/emsdk - 3fbbd97b47b5a71d7cf3ca2e197b0b93feaf975d + ea10b4e5534de1806cc2e84ddd3b00eabcab962f https://github.com/dotnet/wcf @@ -54,129 +54,129 @@ - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 https://github.com/microsoft/vstest 140434f7109d357d0158ade9e5164a4861513965 - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf https://github.com/dotnet/llvm-project @@ -210,53 +210,53 @@ https://github.com/dotnet/llvm-project 54cc196d506692c366d9e116cdb3a9a56342f720 - + https://github.com/dotnet/runtime - 2b0d0d164aac758b1181329f97c87819e203617c + f21ace52e357bbf0019da5c9e42d66705a087235 - + https://github.com/dotnet/runtime - 2b0d0d164aac758b1181329f97c87819e203617c + f21ace52e357bbf0019da5c9e42d66705a087235 - + https://github.com/dotnet/runtime - 2b0d0d164aac758b1181329f97c87819e203617c + f21ace52e357bbf0019da5c9e42d66705a087235 - + https://github.com/dotnet/runtime - 2b0d0d164aac758b1181329f97c87819e203617c + f21ace52e357bbf0019da5c9e42d66705a087235 - + https://github.com/dotnet/runtime - 2b0d0d164aac758b1181329f97c87819e203617c + f21ace52e357bbf0019da5c9e42d66705a087235 - + https://github.com/dotnet/runtime - 2b0d0d164aac758b1181329f97c87819e203617c + f21ace52e357bbf0019da5c9e42d66705a087235 - + https://github.com/dotnet/runtime - 2b0d0d164aac758b1181329f97c87819e203617c + f21ace52e357bbf0019da5c9e42d66705a087235 - + https://github.com/dotnet/linker - 17033869c8e75e3805ba42af4c5509af72c8bb72 + 1481a51970586b26208a7bc6173dc77d658f3508 - + https://github.com/dotnet/xharness - 15aa00a936f7ac3f25358a82e795df12bc7710da + a1d9a67e971fc0b8724507847491fe93f65728db - + https://github.com/dotnet/xharness - 15aa00a936f7ac3f25358a82e795df12bc7710da + a1d9a67e971fc0b8724507847491fe93f65728db - + https://github.com/dotnet/xharness - 15aa00a936f7ac3f25358a82e795df12bc7710da + a1d9a67e971fc0b8724507847491fe93f65728db - + https://github.com/dotnet/arcade - ccfe6da198c5f05534863bbb1bff66e830e0c6ab + ba1c3aff4be864c493031d989259ef92aaa23fc3 https://dev.azure.com/dnceng/internal/_git/dotnet-optimization @@ -278,13 +278,13 @@ https://github.com/dotnet/hotreload-utils 3c641f5b79f90b0341bc0b6f728bae56ede711fd - + https://github.com/dotnet/runtime-assets - 371af1f99788b76eae14b96aad4ab7ac9b373938 + 0920468fa7db4ee8ea8bbcba186421cb92713adf - + https://github.com/dotnet/roslyn-analyzers - 0e7f40d1709f0d7ffd316d89e452151a7365354b + 114d5f2927b8afc90f169df80fdcbe8c7a644bac https://github.com/dotnet/sdk diff --git a/eng/Versions.props b/eng/Versions.props index 865ba86f68d0f..981629491f417 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -44,40 +44,40 @@ 4.3.0-1.22206.2 4.3.0-1.22206.2 4.3.0-1.22206.2 - 7.0.0-preview1.22310.1 + 7.0.0-preview1.22302.1 4.3.0-1.22206.2 - 4.4.0-1.22315.13 + 4.3.0-3.22281.14 2.0.0-preview.4.22252.4 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 2.5.1-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 - 7.0.0-beta.22316.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 2.5.1-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 + 7.0.0-beta.22255.2 6.0.0-preview.1.102 - 7.0.0-preview.6.22319.5 - 7.0.0-preview.6.22319.5 - 7.0.0-preview.6.22319.5 + 7.0.0-preview.6.22305.4 + 7.0.0-preview.6.22305.4 + 7.0.0-preview.6.22305.4 3.1.0 - 7.0.0-preview.6.22319.5 + 7.0.0-preview.6.22305.4 1.0.0-alpha.1.22252.1 1.0.0-alpha.1.22252.1 1.0.0-alpha.1.22252.1 @@ -111,25 +111,25 @@ 5.0.0 5.0.0 4.9.0 - 7.0.0-preview.6.22319.5 + 7.0.0-preview.6.22305.4 6.0.0 4.5.4 4.5.0 - 7.0.0-preview.6.22319.5 + 7.0.0-preview.6.22305.4 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 - 7.0.0-beta.22313.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 + 7.0.0-beta.22281.1 1.0.0-prerelease.22279.1 1.0.0-prerelease.22279.1 @@ -150,9 +150,9 @@ 1.1.0 16.9.0-preview-20201201-01 - 1.0.0-prerelease.22320.3 - 1.0.0-prerelease.22320.3 - 1.0.0-prerelease.22320.3 + 1.0.0-prerelease.22305.1 + 1.0.0-prerelease.22305.1 + 1.0.0-prerelease.22305.1 1.1.0-alpha.0.22306.2 2.4.2-pre.22 0.12.0-pre.20 @@ -168,10 +168,10 @@ 7.0.0-preview-20220608.1 - 7.0.100-1.22320.3 + 7.0.100-1.22306.1 $(MicrosoftNETILLinkTasksVersion) - 7.0.0-preview.6.22320.2 + 7.0.0-preview.6.22306.1 7.0.0-alpha.1.22301.1 @@ -184,7 +184,7 @@ 11.1.0-alpha.1.22259.2 11.1.0-alpha.1.22259.2 - 7.0.0-preview.6.22320.1 + 7.0.0-preview.6.22281.1 $(MicrosoftNETWorkloadEmscriptenManifest70100Version) 1.1.87-gba258badda diff --git a/eng/build.sh b/eng/build.sh index 21784abd80be3..9c9beb471f1fb 100755 --- a/eng/build.sh +++ b/eng/build.sh @@ -17,7 +17,7 @@ scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" usage() { echo "Common settings:" - echo " --arch (-a) Target platform: x86, x64, arm, armv6, armel, arm64, loongarch64, s390x, ppc64le or wasm." + echo " --arch (-a) Target platform: x86, x64, arm, armv6, armel, arm64, loongarch64, s390x or wasm." echo " [Default: Your machine's architecture.]" echo " --binaryLog (-bl) Output binary log." echo " --cross Optional argument to signify cross compilation." @@ -206,12 +206,12 @@ while [[ $# > 0 ]]; do fi passedArch="$(echo "$2" | tr "[:upper:]" "[:lower:]")" case "$passedArch" in - x64|x86|arm|armv6|armel|arm64|loongarch64|s390x|ppc64le|wasm) + x64|x86|arm|armv6|armel|arm64|loongarch64|s390x|wasm) arch=$passedArch ;; *) echo "Unsupported target architecture '$2'." - echo "The allowed values are x86, x64, arm, armv6, armel, arm64, loongarch64, s390x, ppc64le and wasm." + echo "The allowed values are x86, x64, arm, armv6, armel, arm64, loongarch64, s390x, and wasm." exit 1 ;; esac diff --git a/eng/common/init-tools-native.ps1 b/eng/common/init-tools-native.ps1 index 24a5e65de1b3e..413adea4365b1 100644 --- a/eng/common/init-tools-native.ps1 +++ b/eng/common/init-tools-native.ps1 @@ -93,7 +93,7 @@ try { $ToolVersion = "" } $ArcadeToolsDirectory = "C:\arcade-tools" - if (-not (Test-Path $ArcadeToolsDirectory)) { + if (Test-Path $ArcadeToolsDirectory -eq $False) { Write-Error "Arcade tools directory '$ArcadeToolsDirectory' was not found; artifacts were not properly installed." exit 1 } @@ -103,14 +103,13 @@ try { exit 1 } $BinPathFile = "$($ToolDirectory.FullName)\binpath.txt" - if (-not (Test-Path -Path "$BinPathFile")) { + if (Test-Path -Path "$BinPathFile" -eq $False) { Write-Error "Unable to find binpath.txt in '$($ToolDirectory.FullName)' ($ToolName $ToolVersion); artifact is either installed incorrectly or is not a bootstrappable tool." exit 1 } $BinPath = Get-Content "$BinPathFile" - $ToolPath = Convert-Path -Path $BinPath - Write-Host "Adding $ToolName to the path ($ToolPath)..." - Write-Host "##vso[task.prependpath]$ToolPath" + Write-Host "Adding $ToolName to the path ($(Convert-Path -Path $BinPath))..." + Write-Host "##vso[task.prependpath]$(Convert-Path -Path $BinPath)" } } exit 0 @@ -189,7 +188,7 @@ try { Write-Host "##vso[task.prependpath]$(Convert-Path -Path $InstallBin)" return $InstallBin } - elseif (-not ($PathPromotion)) { + else { Write-PipelineTelemetryError -Category 'NativeToolsBootstrap' -Message 'Native tools install directory does not exist, installation failed' exit 1 } diff --git a/eng/common/native/init-compiler.sh b/eng/common/native/init-compiler.sh index 6d7ba15e5f2b5..4b99a9cad3b77 100644 --- a/eng/common/native/init-compiler.sh +++ b/eng/common/native/init-compiler.sh @@ -71,7 +71,7 @@ if [[ -z "$CLR_CC" ]]; then # Set default versions if [[ -z "$majorVersion" ]]; then # note: gcc (all versions) and clang versions higher than 6 do not have minor version in file name, if it is zero. - if [[ "$compiler" == "clang" ]]; then versions=( 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) + if [[ "$compiler" == "clang" ]]; then versions=( 14 13 12 11 10 9 8 7 6.0 5.0 4.0 3.9 3.8 3.7 3.6 3.5 ) elif [[ "$compiler" == "gcc" ]]; then versions=( 12 11 10 9 8 7 6 5 4.9 ); fi for version in "${versions[@]}"; do diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 423bd962e9661..797f05292a851 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -635,10 +635,6 @@ function InitializeNativeTools() { InstallDirectory = "$ToolsDir" } } - if (Test-Path variable:NativeToolsOnMachine) { - Write-Host "Variable NativeToolsOnMachine detected, enabling native tool path promotion..." - $nativeArgs += @{ PathPromotion = $true } - } & "$PSScriptRoot/init-tools-native.ps1" @nativeArgs } } diff --git a/eng/native/build-commons.sh b/eng/native/build-commons.sh index 1b28031ab4de4..dca61277f7fff 100755 --- a/eng/native/build-commons.sh +++ b/eng/native/build-commons.sh @@ -197,7 +197,7 @@ usage() echo "" echo "Common Options:" echo "" - echo "BuildArch can be: -arm, -armv6, -armel, -arm64, -loongarch64, -s390x, -ppc64le, x64, x86, -wasm" + echo "BuildArch can be: -arm, -armv6, -armel, -arm64, -loongarch64, -s390x, x64, x86, -wasm" echo "BuildType can be: -debug, -checked, -release" echo "-os: target OS (defaults to running OS)" echo "-bindir: output directory (defaults to $__ProjectRoot/artifacts)" @@ -392,10 +392,6 @@ while :; do __TargetArch=wasm ;; - ppc64le|-ppc64le) - __TargetArch=ppc64le - ;; - os|-os) if [[ -n "$2" ]]; then __TargetOS="$2" diff --git a/eng/native/configurecompiler.cmake b/eng/native/configurecompiler.cmake index 047999bded88f..931cecdeddb5b 100644 --- a/eng/native/configurecompiler.cmake +++ b/eng/native/configurecompiler.cmake @@ -236,9 +236,6 @@ elseif (CLR_CMAKE_HOST_ARCH_WASM) elseif (CLR_CMAKE_HOST_ARCH_MIPS64) set(ARCH_HOST_NAME mips64) add_definitions(-DHOST_MIPS64 -DHOST_64BIT=1) -elseif (CLR_CMAKE_HOST_ARCH_POWERPC64) - set(ARCH_HOST_NAME ppc64le) - add_definitions(-DHOST_POWERPC64 -DHOST_64BIT) else () clr_unknown_arch() endif () @@ -259,8 +256,6 @@ if (CLR_CMAKE_HOST_UNIX) message("Detected Linux i686") elseif(CLR_CMAKE_HOST_UNIX_S390X) message("Detected Linux s390x") - elseif(CLR_CMAKE_HOST_UNIX_POWERPC64) - message("Detected Linux ppc64le") else() clr_unknown_arch() endif() @@ -337,11 +332,6 @@ elseif (CLR_CMAKE_TARGET_ARCH_S390X) set(ARCH_SOURCES_DIR s390x) add_compile_definitions($<$>>:TARGET_S390X>) add_compile_definitions($<$>>:TARGET_64BIT>) -elseif (CLR_CMAKE_TARGET_ARCH_POWERPC64) - set(ARCH_TARGET_NAME ppc64le) - set(ARCH_SOURCES_DIR ppc64le) - add_compile_definitions($<$>>:TARGET_POWERPC64>) - add_compile_definitions($<$>>:TARGET_64BIT>) elseif (CLR_CMAKE_TARGET_ARCH_WASM) set(ARCH_TARGET_NAME wasm) set(ARCH_SOURCES_DIR wasm) diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake index d21206f1f8bca..573d57f9ed0dd 100644 --- a/eng/native/configureplatform.cmake +++ b/eng/native/configureplatform.cmake @@ -51,8 +51,6 @@ if(CLR_CMAKE_HOST_OS STREQUAL Linux) set(CLR_CMAKE_HOST_UNIX_X86 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL s390x) set(CLR_CMAKE_HOST_UNIX_S390X 1) - elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL ppc64le) - set(CLR_CMAKE_HOST_UNIX_POWERPC64 1) elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL mips64) set(CLR_CMAKE_HOST_UNIX_MIPS64 1) else() @@ -252,9 +250,6 @@ elseif(CLR_CMAKE_HOST_UNIX_X86) elseif(CLR_CMAKE_HOST_UNIX_S390X) set(CLR_CMAKE_HOST_ARCH_S390X 1) set(CLR_CMAKE_HOST_ARCH "s390x") -elseif(CLR_CMAKE_HOST_UNIX_POWERPC64) - set(CLR_CMAKE_HOST_ARCH_POWERPC64 1) - set(CLR_CMAKE_HOST_ARCH "ppc64le") elseif(CLR_CMAKE_HOST_BROWSER) set(CLR_CMAKE_HOST_ARCH_WASM 1) set(CLR_CMAKE_HOST_ARCH "wasm") @@ -308,8 +303,6 @@ if (CLR_CMAKE_TARGET_ARCH STREQUAL x64) set(ARM_SOFTFP 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL s390x) set(CLR_CMAKE_TARGET_ARCH_S390X 1) - elseif(CLR_CMAKE_TARGET_ARCH STREQUAL ppc64le) - set(CLR_CMAKE_TARGET_ARCH_POWERPC64 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL wasm) set(CLR_CMAKE_TARGET_ARCH_WASM 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL mips64) @@ -420,8 +413,6 @@ if(CLR_CMAKE_TARGET_UNIX) set(CLR_CMAKE_TARGET_UNIX_X86 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL s390x) set(CLR_CMAKE_TARGET_UNIX_S390X 1) - elseif(CLR_CMAKE_TARGET_ARCH STREQUAL ppc64le) - set(CLR_CMAKE_TARGET_UNIX_POWERPC64 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL wasm) set(CLR_CMAKE_TARGET_UNIX_WASM 1) elseif(CLR_CMAKE_TARGET_ARCH STREQUAL mips64) diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake index 6697524c6596a..3437ce7cdae64 100644 --- a/eng/native/configuretools.cmake +++ b/eng/native/configuretools.cmake @@ -53,7 +53,7 @@ if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER) if(CLR_CMAKE_TARGET_ANDROID) set(TOOLSET_PREFIX ${ANDROID_TOOLCHAIN_PREFIX}) elseif(CMAKE_CROSSCOMPILING AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD AND - CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv8l|armv7l|armv6l|aarch64|arm|s390x|ppc64le)$") + CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv8l|armv7l|armv6l|aarch64|arm|s390x)$") set(TOOLSET_PREFIX "${TOOLCHAIN}-") else() set(TOOLSET_PREFIX "") diff --git a/eng/native/functions.cmake b/eng/native/functions.cmake index 6a8c8f24e9a79..eaef0d65df066 100644 --- a/eng/native/functions.cmake +++ b/eng/native/functions.cmake @@ -175,10 +175,6 @@ function(find_unwind_libs UnwindLibs) find_library(UNWIND_ARCH NAMES unwind-s390x) endif() - if(CLR_CMAKE_HOST_ARCH_POWERPC64) - find_library(UNWIND_ARCH NAMES unwind-ppc64le) - endif() - if(NOT UNWIND_ARCH STREQUAL UNWIND_ARCH-NOTFOUND) set(UNWIND_LIBS ${UNWIND_ARCH}) endif() diff --git a/eng/native/init-os-and-arch.sh b/eng/native/init-os-and-arch.sh index ded32e3f755f3..7a5815081ad2a 100644 --- a/eng/native/init-os-and-arch.sh +++ b/eng/native/init-os-and-arch.sh @@ -66,9 +66,6 @@ case "$CPUName" in arch=s390x ;; - ppc64le) - arch=ppc64le - ;; *) echo "Unknown CPU $CPUName detected, configuring as if for x64" arch=x64 diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index c491422ae7bce..fca410fcb4b42 100644 --- a/eng/native/tryrun.cmake +++ b/eng/native/tryrun.cmake @@ -68,7 +68,7 @@ if(DARWIN) else() message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm64 or x64 is supported for OSX cross build!") endif() -elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|s390x|ppc64le|x86)$" OR FREEBSD OR ILLUMOS) +elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|s390x|x86)$" OR FREEBSD OR ILLUMOS) set_cache_value(FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL_EXITCODE 1) set_cache_value(GETPWUID_R_SETS_ERRNO_EXITCODE 0) set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 0) @@ -146,9 +146,9 @@ elseif(TARGET_ARCH_NAME MATCHES "^(armel|arm|armv6|arm64|loongarch64|s390x|ppc64 set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) endif() else() - message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, armv6, arm64, loongarch64, s390x, ppc64le and x86 are supported!") + message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only armel, arm, armv6, arm64, loongarch64, s390x and x86 are supported!") endif() -if(TARGET_ARCH_NAME STREQUAL "x86" OR TARGET_ARCH_NAME STREQUAL "s390x" OR TARGET_ARCH_NAME STREQUAL "armv6" OR TARGET_ARCH_NAME STREQUAL "loongarch64" OR TARGET_ARCH_NAME STREQUAL "ppc64le") +if(TARGET_ARCH_NAME STREQUAL "x86" OR TARGET_ARCH_NAME STREQUAL "s390x" OR TARGET_ARCH_NAME STREQUAL "armv6" OR TARGET_ARCH_NAME STREQUAL "loongarch64") set_cache_value(HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES_EXITCODE 0) endif() diff --git a/eng/pipelines/common/templates/runtimes/run-test-job.yml b/eng/pipelines/common/templates/runtimes/run-test-job.yml index d977f6c692efa..9e75af0ac8f6b 100644 --- a/eng/pipelines/common/templates/runtimes/run-test-job.yml +++ b/eng/pipelines/common/templates/runtimes/run-test-job.yml @@ -227,13 +227,13 @@ jobs: timeoutInMinutes: 300 ${{ else }}: timeoutInMinutes: 200 - ${{ if in(parameters.testGroup, 'outerloop', 'jit-experimental', 'jit-cfg') }}: + ${{ if in(parameters.testGroup, 'outerloop', 'jit-experimental', 'pgo', 'jit-cfg') }}: timeoutInMinutes: 270 ${{ if in(parameters.testGroup, 'gc-longrunning', 'gc-simulator') }}: timeoutInMinutes: 480 ${{ if in(parameters.testGroup, 'jitstress', 'jitstress-isas-arm', 'jitstressregs-x86', 'jitstressregs', 'jitstress2-jitstressregs', 'gcstress0x3-gcstress0xc', 'ilasm') }}: timeoutInMinutes: 390 - ${{ if in(parameters.testGroup, 'gcstress-extra', 'r2r-extra', 'clrinterpreter', 'pgo') }}: + ${{ if in(parameters.testGroup, 'gcstress-extra', 'r2r-extra', 'clrinterpreter') }}: timeoutInMinutes: 510 ${{ if eq(parameters.testGroup, 'jitstress-isas-x86') }}: timeoutInMinutes: 960 @@ -397,7 +397,7 @@ jobs: ${{ if eq(parameters.runtimeFlavor, 'mono') }}: # tiered compilation isn't done on mono yet scenarios: - - normal + - normal ${{ elseif eq(variables['Build.Reason'], 'PullRequest') }}: scenarios: - no_tiered_compilation @@ -545,9 +545,7 @@ jobs: - defaultpgo - dynamicpgo - fullpgo - - fullpgo_methodprofiling - fullpgo_random_gdv - - fullpgo_random_gdv_methodprofiling_only - fullpgo_random_edge - fullpgo_random_gdv_edge ${{ if in(parameters.testGroup, 'gc-longrunning') }}: @@ -570,6 +568,7 @@ jobs: - jitelthookenabled_tiered ${{ if in(parameters.testGroup, 'jit-experimental') }}: scenarios: + - jitosr - jitosr_stress - jitosr_pgo - jitosr_stress_random diff --git a/eng/pipelines/common/templates/wasm-library-aot-tests.yml b/eng/pipelines/common/templates/wasm-library-aot-tests.yml index 170be62247ca4..982002ce90520 100644 --- a/eng/pipelines/common/templates/wasm-library-aot-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-aot-tests.yml @@ -8,7 +8,6 @@ parameters: platforms: [] runAOT: false runSmokeOnlyArg: '' - shouldContinueOnError: false jobs: @@ -24,4 +23,3 @@ jobs: extraHelixArgs: /p:NeedsToBuildWasmAppsOnHelix=true ${{ parameters.extraHelixArgs }} alwaysRun: ${{ parameters.alwaysRun }} runSmokeOnlyArg: $(_runSmokeTestsOnlyArg) - shouldContinueOnError: ${{ parameters.shouldContinueOnError }} diff --git a/eng/pipelines/common/templates/wasm-library-tests.yml b/eng/pipelines/common/templates/wasm-library-tests.yml index 365ea7386d400..8ebf5646fc7e5 100644 --- a/eng/pipelines/common/templates/wasm-library-tests.yml +++ b/eng/pipelines/common/templates/wasm-library-tests.yml @@ -7,7 +7,6 @@ parameters: platforms: [] runSmokeOnlyArg: '' scenarios: ['normal'] - shouldContinueOnError: false jobs: @@ -21,7 +20,6 @@ jobs: buildConfig: Release runtimeFlavor: mono platforms: ${{ parameters.platforms }} - shouldContinueOnError: ${{ parameters.shouldContinueOnError }} variables: # map dependencies variables to local variables - name: librariesContainsChange diff --git a/eng/pipelines/coreclr/libraries-pgo.yml b/eng/pipelines/coreclr/libraries-pgo.yml index 0a3346141744f..0914451b55ec6 100644 --- a/eng/pipelines/coreclr/libraries-pgo.yml +++ b/eng/pipelines/coreclr/libraries-pgo.yml @@ -47,7 +47,7 @@ jobs: helixQueueGroup: libraries helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml jobParameters: - timeoutInMinutes: 600 + timeoutInMinutes: 150 testScope: innerloop liveRuntimeBuildConfig: checked dependsOnTestBuildConfiguration: Release diff --git a/eng/pipelines/coreclr/templates/build-job.yml b/eng/pipelines/coreclr/templates/build-job.yml index fd077f2e85558..74e6b3cfaf0f0 100644 --- a/eng/pipelines/coreclr/templates/build-job.yml +++ b/eng/pipelines/coreclr/templates/build-job.yml @@ -224,8 +224,6 @@ jobs: # Run CoreCLR Tools unit tests - ${{ if eq(parameters.testGroup, 'clrTools') }}: - - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset libs $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(officialBuildIdArg) -ci - displayName: Build libs - script: $(Build.SourcesDirectory)$(dir)build$(scriptExt) -subset clr.toolstests $(crossArg) -arch $(archType) $(osArg) -c $(buildConfig) $(officialBuildIdArg) -ci -test displayName: Run CoreCLR Tools unit tests diff --git a/eng/pipelines/libraries/run-test-job.yml b/eng/pipelines/libraries/run-test-job.yml index c6fbe831a4d9b..17e3a63875d17 100644 --- a/eng/pipelines/libraries/run-test-job.yml +++ b/eng/pipelines/libraries/run-test-job.yml @@ -173,11 +173,10 @@ jobs: - defaultpgo - dynamicpgo - fullpgo - - fullpgo_methodprofiling - fullpgo_random_gdv - - fullpgo_random_gdv_methodprofiling_only - fullpgo_random_edge - fullpgo_random_gdv_edge + - jitosr - jitosr_stress - jitosr_stress_random - jitosr_pgo diff --git a/eng/pipelines/runtime-extra-platforms-other.yml b/eng/pipelines/runtime-extra-platforms-other.yml index 53acaa8c3ee18..dd8a6e0da07b1 100644 --- a/eng/pipelines/runtime-extra-platforms-other.yml +++ b/eng/pipelines/runtime-extra-platforms-other.yml @@ -72,35 +72,6 @@ jobs: eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), eq(variables['isRollingBuild'], true)) -# -# CoreCLR NativeAOT release build and additional libraries tests that are known to be passing -# Only when CoreCLR or library is changed -# -- template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/common/global-build-job.yml - helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml - buildConfig: Release - platforms: - - windows_x64 - - windows_arm64 - jobParameters: - testGroup: innerloop - isSingleFile: true - nameSuffix: NativeAOT_Libs_Passing - buildArgs: -s clr.alljits+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true - timeoutInMinutes: 180 - # extra steps, run tests - extraStepsTemplate: /eng/pipelines/libraries/helix.yml - extraStepsParameters: - creator: dotnet-bot - testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig) - condition: >- - or( - eq(dependencies.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true), - eq(dependencies.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), - eq(variables['isRollingBuild'], true)) - # Run net48 tests on win-x64 - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -226,7 +197,7 @@ jobs: jobParameters: testGroup: innerloop nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true + buildArgs: -s mono+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true $(_runSmokeTestsOnlyArg) /p:BuildTestsOnHelix=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true timeoutInMinutes: 180 condition: >- or( @@ -390,7 +361,7 @@ jobs: jobParameters: testGroup: innerloop nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) /p:EnableAdditionalTimezoneChecks=true + buildArgs: -s mono+libs+host+packs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true $(_runSmokeTestsOnlyArg) timeoutInMinutes: 180 condition: >- or( diff --git a/eng/pipelines/runtime-staging.yml b/eng/pipelines/runtime-staging.yml index bc75954dfe096..35cc083b840b7 100644 --- a/eng/pipelines/runtime-staging.yml +++ b/eng/pipelines/runtime-staging.yml @@ -97,8 +97,6 @@ jobs: platforms: - Browser_wasm_firefox browser: firefox - # ff tests are unstable currently - shouldContinueOnError: true alwaysRun: ${{ variables.isRollingBuild }} # diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 301809c16cb37..6e588b348712f 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -260,8 +260,8 @@ jobs: testGroup: innerloop isSingleFile: true nameSuffix: NativeAOT - buildArgs: -s clr.alljits+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:RunSmokeTestsOnly=true /p:ArchiveTests=true - timeoutInMinutes: 180 + buildArgs: -s clr.alljits+clr.tools+clr.nativeaotlibs+clr.nativeaotruntime+libs+libs.tests -c $(_BuildConfig) /p:TestNativeAot=true /p:ArchiveTests=true + timeoutInMinutes: 120 # extra steps, run tests extraStepsTemplate: /eng/pipelines/libraries/helix.yml extraStepsParameters: @@ -433,7 +433,7 @@ jobs: jobParameters: testGroup: innerloop nameSuffix: AllSubsets_Mono - buildArgs: -s mono+libs+libs.tests+host+packs -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:RunSmokeTestsOnly=true /p:BuildTestsOnHelix=true /p:EnableAdditionalTimezoneChecks=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true + buildArgs: -s mono+libs+libs.tests+host+packs -c $(_BuildConfig) /p:ArchiveTests=true /p:DevTeamProvisioning=- /p:RunAOTCompilation=true /p:RunSmokeTestsOnly=true /p:BuildTestsOnHelix=true /p:UsePortableRuntimePack=true /p:BuildDarwinFrameworks=true timeoutInMinutes: 180 condition: >- or( diff --git a/eng/testing/tests.props b/eng/testing/tests.props index 7ed95b94326e3..e91ec1bbcf0e3 100644 --- a/eng/testing/tests.props +++ b/eng/testing/tests.props @@ -10,6 +10,18 @@ true + + + <_withCategories Condition="'$(WithCategories)' != ''">;$(WithCategories.Trim(';')) + <_withoutCategories Condition="'$(WithoutCategories)' != ''">;$(WithoutCategories.Trim(';')) + + all + <_withCategories Condition="'$(TestScope)' == 'outerloop'">$(_withCategories);OuterLoop + <_withoutCategories Condition="'$(ArchiveTests)' == 'true'">$(_withoutCategories);IgnoreForCI + <_withoutCategories Condition="'$(TestScope)' == '' or '$(TestScope)' == 'innerloop'">$(_withoutCategories);OuterLoop + <_withoutCategories Condition="!$(_withCategories.Contains('failing'))">$(_withoutCategories);failing + + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleTestRunner', '$(Configuration)', '$(NetCoreAppCurrent)')) diff --git a/eng/testing/tests.targets b/eng/testing/tests.targets index c358ff594f3db..df308f3182d44 100644 --- a/eng/testing/tests.targets +++ b/eng/testing/tests.targets @@ -36,18 +36,6 @@ $(RunScriptHostDir)dotnet - - - <_withCategories Condition="'$(WithCategories)' != ''">;$(WithCategories.Trim(';')) - <_withoutCategories Condition="'$(WithoutCategories)' != ''">;$(WithoutCategories.Trim(';')) - - all - <_withCategories Condition="'$(TestScope)' == 'outerloop'">$(_withCategories);OuterLoop - <_withoutCategories Condition="'$(ArchiveTests)' == 'true'">$(_withoutCategories);IgnoreForCI - <_withoutCategories Condition="'$(TestScope)' == '' or '$(TestScope)' == 'innerloop'">$(_withoutCategories);OuterLoop - <_withoutCategories Condition="!$(_withCategories.Contains('failing'))">$(_withoutCategories);failing - - <_MonoAotCrossCompilerPath>$([MSBuild]::NormalizePath($(MonoAotCrossDir), 'mono-aot-cross')) diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index 4c5310cb696f9..7f5cdb654efe6 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -5,10 +5,6 @@ true $(BundleTestAppTargets);BundleTestWasmApp true - - true - - $(NoWarn);IL2118 $([MSBuild]::NormalizeDirectory($(MonoProjectRoot), 'wasm', 'emsdk')) @@ -303,8 +299,4 @@ - - - - diff --git a/eng/testing/xunit/xunit.console.targets b/eng/testing/xunit/xunit.console.targets index 75d73d1037442..77d7363a22f4e 100644 --- a/eng/testing/xunit/xunit.console.targets +++ b/eng/testing/xunit/xunit.console.targets @@ -36,11 +36,6 @@ $(_withoutCategories.Replace(';', '%0dcategory=')) - - - $(RunScriptCommand) -xml $(TestResultsName) - - (T[] incoming, int requiredSize) private int m_length; private byte[] m_ILStream; - private __LabelInfo[]? m_labelList; + private int[]? m_labelList; private int m_labelCount; private __FixupData[]? m_fixupData; @@ -61,13 +61,10 @@ internal static T[] EnlargeArray(T[] incoming, int requiredSize) internal int m_localCount; internal SignatureHelper m_localSignature; - private int m_curDepth; // Current stack depth, with -1 meaning unknown. - private int m_targetDepth; // Stack depth at a target of the previous instruction (when it is branching). - private int m_maxDepth; // Running max of the stack depth. + private int m_maxStackSize; // Maximum stack size not counting the exceptions. - // Adjustment to add to m_maxDepth for incorrect/invalid IL. For example, when branch instructions - // with different stack depths target the same label. - private long m_depthAdjustment; + private int m_maxMidStack; // Maximum stack size for a given basic block. + private int m_maxMidStackCur; // Running count of the maximum stack size for the current basic block. internal int CurrExcStackCount => m_currExcStackCount; @@ -134,32 +131,28 @@ internal void UpdateStackSize(OpCode opcode, int stackchange) // requirements for the function. stackchange specifies the amount // by which the stacksize needs to be updated. - if (m_curDepth < 0) - { - // Current depth is "unknown". We get here when: - // * this is unreachable code. - // * the client uses explicit numeric offsets rather than Labels. - m_curDepth = 0; - } - - m_curDepth += stackchange; - if (m_curDepth < 0) + // Special case for the Return. Returns pops 1 if there is a + // non-void return value. + + // Update the running stacksize. m_maxMidStack specifies the maximum + // amount of stack required for the current basic block irrespective of + // where you enter the block. + m_maxMidStackCur += stackchange; + if (m_maxMidStackCur > m_maxMidStack) + m_maxMidStack = m_maxMidStackCur; + else if (m_maxMidStackCur < 0) + m_maxMidStackCur = 0; + + // If the current instruction signifies end of a basic, which basically + // means an unconditional branch, add m_maxMidStack to m_maxStackSize. + // m_maxStackSize will eventually be the sum of the stack requirements for + // each basic block. + if (opcode.EndsUncondJmpBlk()) { - // Stack underflow. Assume our previous depth computation was flawed. - m_depthAdjustment -= m_curDepth; - m_curDepth = 0; + m_maxStackSize += m_maxMidStack; + m_maxMidStack = 0; + m_maxMidStackCur = 0; } - else if (m_maxDepth < m_curDepth) - m_maxDepth = m_curDepth; - Debug.Assert(m_depthAdjustment >= 0); - Debug.Assert(m_curDepth >= 0); - - // Record the stack depth at a "target" of this instruction. - m_targetDepth = m_curDepth; - - // If the current instruction can't fall through, set the depth to unknown. - if (opcode.EndsUncondJmpBlk()) - m_curDepth = -1; } private int GetMethodToken(MethodBase method, Type[]? optionalParameterTypes, bool useMethodDef) @@ -287,11 +280,10 @@ private int GetLabelPos(Label lbl) if (index < 0 || index >= m_labelCount || m_labelList is null) throw new ArgumentException(SR.Argument_BadLabel); - int pos = m_labelList[index].m_pos; - if (pos < 0) + if (m_labelList[index] < 0) throw new ArgumentException(SR.Argument_BadLabelContent); - return pos; + return m_labelList[index]; } private void AddFixup(Label lbl, int pos, int instSize) @@ -314,30 +306,11 @@ private void AddFixup(Label lbl, int pos, int instSize) m_fixupLabel = lbl, m_fixupInstSize = instSize }; - - int labelIndex = lbl.GetLabelValue(); - if (labelIndex < 0 || labelIndex >= m_labelCount || m_labelList is null) - throw new ArgumentException(SR.Argument_BadLabel); - - int depth = m_labelList[labelIndex].m_depth; - int targetDepth = m_targetDepth; - Debug.Assert(depth >= -1); - Debug.Assert(targetDepth >= -1); - if (depth < targetDepth) - { - // Either unknown depth for this label or this branch location has a larger depth than previously recorded. - // In the latter case, the IL is (likely) invalid, but we just compensate for it. - if (depth >= 0) - m_depthAdjustment += targetDepth - depth; - m_labelList[labelIndex].m_depth = targetDepth; - } } internal int GetMaxStackSize() { - // Limit the computed max stack to 2^16 - 1, since the value is mod`ed by 2^16 by other code. - Debug.Assert(m_depthAdjustment >= 0); - return (int)Math.Min(ushort.MaxValue, m_maxDepth + m_depthAdjustment); + return m_maxStackSize; } private static void SortExceptions(__ExceptionInfo[] exceptions) @@ -953,7 +926,7 @@ public virtual Label BeginExceptionBlock() m_currExcStack = EnlargeArray(m_currExcStack); } - Label endLabel = DefineLabel(0); + Label endLabel = DefineLabel(); __ExceptionInfo exceptionInfo = new __ExceptionInfo(m_length, endLabel); // add the exception to the tracking list @@ -961,10 +934,6 @@ public virtual Label BeginExceptionBlock() // Make this exception the current active exception m_currExcStack[m_currExcStackCount++] = exceptionInfo; - - // Stack depth for "try" starts at zero. - m_curDepth = 0; - return endLabel; } @@ -1000,7 +969,7 @@ public virtual void EndExceptionBlock() // Check if we've already set this label. // The only reason why we might have set this is if we have a finally block. - Label label = m_labelList![endLabel.GetLabelValue()].m_pos != -1 + Label label = m_labelList![endLabel.GetLabelValue()] != -1 ? current.m_finallyEndLabel : endLabel; @@ -1021,12 +990,9 @@ public virtual void BeginExceptFilterBlock() Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFilterAddr(m_length); - - // Stack depth for "filter" starts at one. - m_curDepth = 1; } - public virtual void BeginCatchBlock(Type? exceptionType) + public virtual void BeginCatchBlock(Type exceptionType) { // Begins a catch block. Emits a branch instruction to the end of the current exception block. @@ -1054,9 +1020,6 @@ public virtual void BeginCatchBlock(Type? exceptionType) } current.MarkCatchAddr(m_length, exceptionType); - - // Stack depth for "catch" starts at one. - m_curDepth = 1; } public virtual void BeginFaultBlock() @@ -1071,9 +1034,6 @@ public virtual void BeginFaultBlock() Emit(OpCodes.Leave, current.GetEndLabel()); current.MarkFaultAddr(m_length); - - // Stack depth for "fault" starts at zero. - m_curDepth = 0; } public virtual void BeginFinallyBlock() @@ -1095,7 +1055,7 @@ public virtual void BeginFinallyBlock() MarkLabel(endLabel); - Label finallyEndLabel = DefineLabel(0); + Label finallyEndLabel = DefineLabel(); current.SetFinallyEndLabel(finallyEndLabel); // generate leave for try clause @@ -1103,36 +1063,25 @@ public virtual void BeginFinallyBlock() if (catchEndAddr == 0) catchEndAddr = m_length; current.MarkFinallyAddr(m_length, catchEndAddr); - - // Stack depth for "finally" starts at zero. - m_curDepth = 0; } #endregion #region Labels public virtual Label DefineLabel() - { - // We don't know the stack depth at the label yet, so set it to -1. - return DefineLabel(-1); - } - - private Label DefineLabel(int depth) { // Declares a new Label. This is just a token and does not yet represent any particular location // within the stream. In order to set the position of the label within the stream, you must call // Mark Label. - Debug.Assert(depth >= -1); - // Delay init the label array in case we dont use it - m_labelList ??= new __LabelInfo[DefaultLabelArraySize]; + // Delay init the lable array in case we dont use it + m_labelList ??= new int[DefaultLabelArraySize]; if (m_labelCount >= m_labelList.Length) { m_labelList = EnlargeArray(m_labelList); } - m_labelList[m_labelCount].m_pos = -1; - m_labelList[m_labelCount].m_depth = depth; + m_labelList[m_labelCount] = -1; return new Label(m_labelCount++); } @@ -1149,39 +1098,12 @@ public virtual void MarkLabel(Label loc) throw new ArgumentException(SR.Argument_InvalidLabel); } - if (m_labelList[labelIndex].m_pos != -1) + if (m_labelList[labelIndex] != -1) { throw new ArgumentException(SR.Argument_RedefinedLabel); } - m_labelList[labelIndex].m_pos = m_length; - - int depth = m_labelList[labelIndex].m_depth; - if (depth < 0) - { - // Unknown depth for this label, indicating that it hasn't been used yet. - // If m_curDepth is unknown, we're in the Backward branch constraint case. See ECMA-335 III.1.7.5. - // The m_depthAdjustment field will compensate for violations of this constraint, as we - // discover them. That is, here we assume a depth of zero. If a (later) branch to this label - // has a positive stack depth, we'll record that as the new depth and add the delta into - // m_depthAdjustment. - if (m_curDepth < 0) - m_curDepth = 0; - m_labelList[labelIndex].m_depth = m_curDepth; - } - else if (depth < m_curDepth) - { - // A branch location with smaller stack targets this label. In this case, the IL is - // invalid, but we just compensate for it. - m_depthAdjustment += m_curDepth - depth; - m_labelList[labelIndex].m_depth = m_curDepth; - } - else if (depth > m_curDepth) - { - // Either the current depth is unknown, or a branch location with larger stack targets - // this label, so the IL is invalid. In either case, just adjust the current depth. - m_curDepth = depth; - } + m_labelList[labelIndex] = m_length; } #endregion @@ -1365,12 +1287,6 @@ public virtual void EndScope() #endregion } - internal struct __LabelInfo - { - internal int m_pos; // Position in the il stream, with -1 meaning unknown. - internal int m_depth; // Stack depth, with -1 meaning unknown. - } - internal struct __FixupData { internal Label m_fixupLabel; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs index a5f4fdd8ba7d5..10da169b3e33f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs @@ -309,7 +309,7 @@ internal int GetMaxStack() { if (m_ilGenerator != null) { - return m_ilGenerator.GetMaxStackSize(); + return m_ilGenerator.GetMaxStackSize() + ExceptionHandlerCount; } else { @@ -323,6 +323,8 @@ internal int GetMaxStack() return m_exceptions; } + internal int ExceptionHandlerCount => m_exceptions != null ? m_exceptions.Length : 0; + internal static int CalculateNumberOfExceptions(__ExceptionInfo[]? excp) { int num = 0; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs index 8468e8f9529e8..6acf77be549c0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodInvoker.CoreCLR.cs @@ -15,16 +15,13 @@ public MethodInvoker(MethodBase method, Signature signature) _method = method; _signature = signature; - if (LocalAppContextSwitches.ForceInterpretedInvoke && !LocalAppContextSwitches.ForceEmitInvoke) - { - // Always use the native invoke; useful for testing. - _strategyDetermined = true; - } - else if (LocalAppContextSwitches.ForceEmitInvoke && !LocalAppContextSwitches.ForceInterpretedInvoke) - { - // Always use emit invoke (if IsDynamicCodeCompiled == true); useful for testing. - _invoked = true; - } +#if USE_NATIVE_INVOKE + // Always use the native invoke; useful for testing. + _strategyDetermined = true; +#elif USE_EMIT_INVOKE + // Always use emit invoke (if IsDynamicCodeCompiled == true); useful for testing. + _invoked = true; +#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index fa602e0c1dc39..c6c20002f2cdc 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -134,10 +134,9 @@ public override AssemblyName GetName(bool copiedName) an.RawFlags = GetFlags() | AssemblyNameFlags.PublicKey; -#pragma warning disable IL3000, SYSLIB0044 // System.Reflection.AssemblyName.CodeBase' always returns an empty string for assemblies embedded in a single-file app. - // AssemblyName.CodeBase and AssemblyName.EscapedCodeBase are obsolete. Using them for loading an assembly is not supported. +#pragma warning disable IL3000 // System.Reflection.AssemblyName.CodeBase' always returns an empty string for assemblies embedded in a single-file app. an.CodeBase = GetCodeBase(); -#pragma warning restore IL3000, SYSLIB0044 +#pragma warning restore IL3000 #pragma warning disable SYSLIB0037 // AssemblyName.HashAlgorithm is obsolete an.HashAlgorithm = GetHashAlgorithm(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index 486aeb72faddb..a921099356ec3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -477,12 +477,7 @@ private static CastResult TryGet(nuint source, nuint target) private static object? ChkCastClassSpecial(void* toTypeHnd, object obj) { MethodTable* mt = RuntimeHelpers.GetMethodTable(obj); - - // Normally, this case is expected to be handled by JIT inline. - // However, with PGO data JIT might decide to check a different type instead - // so this one has to be always checked here - if (toTypeHnd == mt) - goto done; + Debug.Assert(mt != toTypeHnd, "The check for the trivial cases should be inlined by the JIT"); for (; ; ) { diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs index 64b547b699fb7..31c98a5bf254a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs @@ -24,7 +24,7 @@ public abstract class ValueType { [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification = "Trimmed fields don't make a difference for equality")] - public override unsafe bool Equals([NotNullWhen(true)] object? obj) + public unsafe override bool Equals([NotNullWhen(true)] object? obj) { if (null == obj) { diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index e23c00dfc2568..b3edff82d7cbc 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -1180,7 +1180,6 @@ HRESULT AssemblyBinderCommon::BindUsingHostAssemblyResolver(/* in */ INT_PTR pMa HRESULT AssemblyBinderCommon::BindUsingPEImage(/* in */ AssemblyBinder* pBinder, /* in */ BINDER_SPACE::AssemblyName *pAssemblyName, /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, /* [retval] [out] */ Assembly **ppAssembly) { HRESULT hr = E_FAIL; @@ -1209,7 +1208,7 @@ HRESULT AssemblyBinderCommon::BindUsingPEImage(/* in */ AssemblyBinder* pBinder pAssemblyName, true, // skipFailureCaching true, // skipVersionCompatibilityCheck - excludeAppPaths, // excludeAppPaths + false, // excludeAppPaths &bindResult); if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) diff --git a/src/coreclr/binder/customassemblybinder.cpp b/src/coreclr/binder/customassemblybinder.cpp index 02a8d2e918dc7..98e0fd25de81b 100644 --- a/src/coreclr/binder/customassemblybinder.cpp +++ b/src/coreclr/binder/customassemblybinder.cpp @@ -102,7 +102,6 @@ Exit:; } HRESULT CustomAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, /* [retval][out] */ BINDER_SPACE::Assembly **ppAssembly) { HRESULT hr = S_OK; @@ -129,7 +128,7 @@ HRESULT CustomAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage, IF_FAIL_GO(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); } - hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, excludeAppPaths, &pCoreCLRFoundAssembly); + hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, &pCoreCLRFoundAssembly); if (hr == S_OK) { _ASSERTE(pCoreCLRFoundAssembly != NULL); diff --git a/src/coreclr/binder/defaultassemblybinder.cpp b/src/coreclr/binder/defaultassemblybinder.cpp index 2461ca4b1397d..28157a11244cd 100644 --- a/src/coreclr/binder/defaultassemblybinder.cpp +++ b/src/coreclr/binder/defaultassemblybinder.cpp @@ -111,7 +111,6 @@ Exit:; #if !defined(DACCESS_COMPILE) HRESULT DefaultAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, /* [retval][out] */ BINDER_SPACE::Assembly **ppAssembly) { HRESULT hr = S_OK; @@ -158,7 +157,7 @@ HRESULT DefaultAssemblyBinder::BindUsingPEImage( /* in */ PEImage *pPEImage, } } - hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, excludeAppPaths, &pCoreCLRFoundAssembly); + hr = AssemblyBinderCommon::BindUsingPEImage(this, pAssemblyName, pPEImage, &pCoreCLRFoundAssembly); if (hr == S_OK) { _ASSERTE(pCoreCLRFoundAssembly != NULL); diff --git a/src/coreclr/binder/inc/assemblybindercommon.hpp b/src/coreclr/binder/inc/assemblybindercommon.hpp index 3bd529bd9c0a9..b3b2158715928 100644 --- a/src/coreclr/binder/inc/assemblybindercommon.hpp +++ b/src/coreclr/binder/inc/assemblybindercommon.hpp @@ -56,7 +56,6 @@ namespace BINDER_SPACE static HRESULT BindUsingPEImage(/* in */ AssemblyBinder *pBinder, /* in */ BINDER_SPACE::AssemblyName *pAssemblyName, /* in */ PEImage *pPEImage, - /* in */ bool excludeAppPaths, /* [retval] [out] */ Assembly **ppAssembly); #endif // !defined(DACCESS_COMPILE) diff --git a/src/coreclr/binder/inc/customassemblybinder.h b/src/coreclr/binder/inc/customassemblybinder.h index 7a89c5033b9e5..9d59832f3c979 100644 --- a/src/coreclr/binder/inc/customassemblybinder.h +++ b/src/coreclr/binder/inc/customassemblybinder.h @@ -18,7 +18,6 @@ class CustomAssemblyBinder final : public AssemblyBinder public: HRESULT BindUsingPEImage(PEImage* pPEImage, - bool excludeAppPaths, BINDER_SPACE::Assembly** ppAssembly) override; HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName, diff --git a/src/coreclr/binder/inc/defaultassemblybinder.h b/src/coreclr/binder/inc/defaultassemblybinder.h index 3d35854e09f3f..398174c65a078 100644 --- a/src/coreclr/binder/inc/defaultassemblybinder.h +++ b/src/coreclr/binder/inc/defaultassemblybinder.h @@ -16,7 +16,6 @@ class DefaultAssemblyBinder final : public AssemblyBinder public: HRESULT BindUsingPEImage(PEImage* pPEImage, - bool excludeAppPaths, BINDER_SPACE::Assembly** ppAssembly) override; HRESULT BindUsingAssemblyName(BINDER_SPACE::AssemblyName* pAssemblyName, diff --git a/src/coreclr/classlibnative/bcltype/system.cpp b/src/coreclr/classlibnative/bcltype/system.cpp index 2f1387ddd2fcf..2d517279fad6f 100644 --- a/src/coreclr/classlibnative/bcltype/system.cpp +++ b/src/coreclr/classlibnative/bcltype/system.cpp @@ -90,6 +90,43 @@ FCIMPL0(INT32, SystemNative::GetExitCode) } FCIMPLEND +FCIMPL0(Object*, SystemNative::GetCommandLineArgs) +{ + FCALL_CONTRACT; + + PTRARRAYREF strArray = NULL; + + HELPER_METHOD_FRAME_BEGIN_RET_1(strArray); + + LPWSTR commandLine; + + commandLine = WszGetCommandLine(); + if (commandLine==NULL) + COMPlusThrowOM(); + + DWORD numArgs = 0; + LPWSTR* argv = SegmentCommandLine(commandLine, &numArgs); + if (!argv) + COMPlusThrowOM(); + + _ASSERTE(numArgs > 0); + + strArray = (PTRARRAYREF) AllocateObjectArray(numArgs, g_pStringClass); + // Copy each argument into new Strings. + for(unsigned int i=0; iGetDataPtr())) + i; + SetObjectReference((OBJECTREF*)destData, (OBJECTREF)str); + } + delete [] argv; + + HELPER_METHOD_FRAME_END(); + + return OBJECTREFToObject(strArray); +} +FCIMPLEND + // Return a method info for the method were the exception was thrown FCIMPL1(ReflectMethodObject*, SystemNative::GetMethodFromStackTrace, ArrayBase* pStackTraceUNSAFE) { diff --git a/src/coreclr/classlibnative/bcltype/system.h b/src/coreclr/classlibnative/bcltype/system.h index b4a773a847c39..27e772be2af07 100644 --- a/src/coreclr/classlibnative/bcltype/system.h +++ b/src/coreclr/classlibnative/bcltype/system.h @@ -43,6 +43,7 @@ class SystemNative static FCDECL1(VOID,SetExitCode,INT32 exitcode); static FCDECL0(INT32, GetExitCode); + static FCDECL0(Object*, GetCommandLineArgs); static FCDECL1(VOID, FailFast, StringObject* refMessageUNSAFE); static FCDECL2(VOID, FailFastWithExitCode, StringObject* refMessageUNSAFE, UINT exitCode); static FCDECL2(VOID, FailFastWithException, StringObject* refMessageUNSAFE, ExceptionObject* refExceptionUNSAFE); diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 55c7a4d0829f9..564aa84cd687e 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -2501,7 +2501,7 @@ namespace serialization { namespace bin { return ErrOverflow; } - memcpy_s(dest, destSize, s.GetUTF8(), cnt); + memcpy_s(dest, destSize, s.GetUTF8NoConvert(), cnt); return cnt; } diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 9fb920f18ed60..6ae350448755d 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -6450,7 +6450,7 @@ HRESULT DacHeapWalker::MoveToNextObject() bool DacHeapWalker::GetSize(TADDR tMT, size_t &size) { - // With heap corruption, it's entirely possible that the MethodTable + // With heap corruption, it's entierly possible that the MethodTable // we get is bad. This could cause exceptions, which we will catch // and return false. This causes the heapwalker to move to the next // segment. @@ -6478,12 +6478,6 @@ bool DacHeapWalker::GetSize(TADDR tMT, size_t &size) size = AlignLarge(size); else size = Align(size); - - // If size == 0, it means we have a heap corruption and - // we will stuck in an infinite loop, so better fail the call now. - ret &= (0 < size); - // Also guard for cases where the size reported is too large and exceeds the high allocation mark. - ret &= ((tMT + size) <= mHeaps[mCurrHeap].Segments[mCurrSeg].End); } EX_CATCH { diff --git a/src/coreclr/debug/daccess/ppc64le/primitives.cpp b/src/coreclr/debug/daccess/ppc64le/primitives.cpp deleted file mode 100644 index 6bbe30049c101..0000000000000 --- a/src/coreclr/debug/daccess/ppc64le/primitives.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// - -#include "stdafx.h" - -#include "../../shared/ppc64le/primitives.cpp" diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 35aac26d72b22..f73b1ce8afa2c 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -647,10 +647,9 @@ ClrDataAccess::GetRegisterName(int regNum, unsigned int count, _Inout_updates_z_ return E_UNEXPECTED; const WCHAR callerPrefix[] = W("caller."); - // Include null terminator in prefixLen/regLen because wcscpy_s will fail otherwise - unsigned int prefixLen = (unsigned int)ARRAY_SIZE(callerPrefix); - unsigned int regLen = (unsigned int)wcslen(regs[regNum]) + 1; - unsigned int needed = (callerFrame ? prefixLen - 1 : 0) + regLen; + unsigned int prefixLen = (unsigned int)ARRAY_SIZE(callerPrefix) - 1; + unsigned int regLen = (unsigned int)wcslen(regs[regNum]); + unsigned int needed = (callerFrame?prefixLen:0) + regLen + 1; if (pNeeded) *pNeeded = needed; @@ -663,8 +662,6 @@ ClrDataAccess::GetRegisterName(int regNum, unsigned int count, _Inout_updates_z_ { unsigned int toCopy = prefixLen < destSize ? prefixLen : destSize; wcscpy_s(curr, toCopy, callerPrefix); - // Point to null terminator - toCopy--; curr += toCopy; destSize -= toCopy; } @@ -673,8 +670,6 @@ ClrDataAccess::GetRegisterName(int regNum, unsigned int count, _Inout_updates_z_ { unsigned int toCopy = regLen < destSize ? regLen : destSize; wcscpy_s(curr, toCopy, regs[regNum]); - // Point to null terminator - toCopy--; curr += toCopy; destSize -= toCopy; } diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index 954836a3e0f74..032e96457ecc1 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -1010,7 +1010,7 @@ MemoryRange Debugger::s_hijackFunction[kMaxHijackFunctions] = RedirectedHandledJITCaseForDbgThreadControl_StubEnd), GetMemoryRangeForFunction(RedirectedHandledJITCaseForUserSuspend_Stub, RedirectedHandledJITCaseForUserSuspend_StubEnd) -#if defined(HAVE_GCCOVER) && defined(TARGET_AMD64) && defined(USE_REDIRECT_FOR_GCSTRESS) +#if defined(HAVE_GCCOVER) && defined(TARGET_AMD64) , GetMemoryRangeForFunction(RedirectedHandledJITCaseForGCStress_Stub, RedirectedHandledJITCaseForGCStress_StubEnd) diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index a5c5ecd0fd620..39b203fa58923 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -2938,7 +2938,7 @@ void RedirectedHandledJITCaseForDbgThreadControl_StubEnd(); void RedirectedHandledJITCaseForUserSuspend_Stub(); void RedirectedHandledJITCaseForUserSuspend_StubEnd(); -#if defined(HAVE_GCCOVER) && defined(TARGET_AMD64) && defined(USE_REDIRECT_FOR_GCSTRESS) +#if defined(HAVE_GCCOVER) && defined(TARGET_AMD64) void RedirectedHandledJITCaseForGCStress_Stub(); void RedirectedHandledJITCaseForGCStress_StubEnd(); #endif // HAVE_GCCOVER && TARGET_AMD64 diff --git a/src/coreclr/debug/ee/functioninfo.cpp b/src/coreclr/debug/ee/functioninfo.cpp index 2b287eb07fcd1..f5f21da3baee8 100644 --- a/src/coreclr/debug/ee/functioninfo.cpp +++ b/src/coreclr/debug/ee/functioninfo.cpp @@ -1518,9 +1518,6 @@ DebuggerJitInfo * DebuggerMethodInfo::FindJitInfo(MethodDesc * pMD, } CONTRACTL_END; -#ifdef TARGET_ARM - addrNativeStartAddr = addrNativeStartAddr|THUMB_CODE; -#endif DebuggerJitInfo * pCheck = m_latestJitInfo; while (pCheck != NULL) diff --git a/src/coreclr/debug/ee/ppc64le/dbghelpers.S b/src/coreclr/debug/ee/ppc64le/dbghelpers.S deleted file mode 100644 index a1ec66394511e..0000000000000 --- a/src/coreclr/debug/ee/ppc64le/dbghelpers.S +++ /dev/null @@ -1,8 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "asmconstants.h" -#include "unixasmmacros.inc" - -#error Unsupported platform - diff --git a/src/coreclr/debug/ee/ppc64le/primitives.cpp b/src/coreclr/debug/ee/ppc64le/primitives.cpp deleted file mode 100644 index 9b2e216d091ca..0000000000000 --- a/src/coreclr/debug/ee/ppc64le/primitives.cpp +++ /dev/null @@ -1,9 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// - -#include "stdafx.h" -#include "threads.h" -#include "../../shared/ppc64le/primitives.cpp" - diff --git a/src/coreclr/debug/shared/ppc64le/primitives.cpp b/src/coreclr/debug/shared/ppc64le/primitives.cpp deleted file mode 100644 index cb4be30c89b56..0000000000000 --- a/src/coreclr/debug/shared/ppc64le/primitives.cpp +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -//***************************************************************************** -// File: primitives.cpp -// - -// -// Platform-specific debugger primitives -// -//***************************************************************************** - -#include "primitives.h" - -#error Unsupported platform - diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index 6a96d6c03e0ea..f6dc44d8b06ee 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -415,6 +415,7 @@ BEGIN IDS_EE_SIZECONTROLBADTYPE "Array size control parameter type not supported." IDS_EE_SAFEARRAYSZARRAYMISMATCH "SafeArray cannot be marshaled to this array type because it has either nonzero lower bounds or more than one dimension." + IDS_EE_ASSEMBLY_GETTYPE_CANNONT_HAVE_ASSEMBLY_SPEC "Type names passed to Assembly.GetType() must not specify an assembly." IDS_EE_NEEDS_ASSEMBLY_SPEC "Typename needs an assembly qualifier." IDS_EE_FILELOAD_ERROR_GENERIC "Could not load file or assembly '%1'. %2" diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index 351ff690aaca6..ed503b4875ad6 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -305,6 +305,7 @@ #define IDS_CLASSLOAD_OVERLAPPING_INTERFACES 0x1a80 #define IDS_CLASSLOAD_32BITCLRLOADING64BITASSEMBLY 0x1a81 +#define IDS_EE_ASSEMBLY_GETTYPE_CANNONT_HAVE_ASSEMBLY_SPEC 0x1a84 #define IDS_EE_NEEDS_ASSEMBLY_SPEC 0x1a87 diff --git a/src/coreclr/gc/env/etmdummy.h b/src/coreclr/gc/env/etmdummy.h index 575e3067cf89a..556372127577a 100644 --- a/src/coreclr/gc/env/etmdummy.h +++ b/src/coreclr/gc/env/etmdummy.h @@ -78,7 +78,6 @@ #define FireEtwThreadPoolWorkerThreadAdjustmentAdjustment(AverageThroughput, NewWorkerThreadCount, Reason, ClrInstanceID) 0 #define FireEtwThreadPoolWorkerThreadAdjustmentStats(Duration, Throughput, ThreadWave, ThroughputWave, ThroughputErrorEstimate, AverageThroughputErrorEstimate, ThroughputRatio, Confidence, NewControlSetting, NewThreadWaveMagnitude, ClrInstanceID) 0 #define FireEtwThreadPoolWorkerThreadWait(ActiveWorkerThreadCount, RetiredWorkerThreadCount, ClrInstanceID) 0 -#define FireEtwThreadPoolMinMaxThreads (MinWorkerThreads, MaxWorkerThreads, MinIOCompletionThreads, MaxIOCompletionThreads, ClrInstanceID) 0 #define FireEtwThreadPoolWorkingThreadCount(Count, ClrInstanceID) 0 #define FireEtwThreadPoolEnqueue(WorkID, ClrInstanceID) 0 #define FireEtwThreadPoolDequeue(WorkID, ClrInstanceID) 0 diff --git a/src/coreclr/gc/env/gcenv.os.h b/src/coreclr/gc/env/gcenv.os.h index 25a15e3847d34..c37f62509e8bc 100644 --- a/src/coreclr/gc/env/gcenv.os.h +++ b/src/coreclr/gc/env/gcenv.os.h @@ -6,6 +6,17 @@ #ifndef __GCENV_OS_H__ #define __GCENV_OS_H__ +#ifdef Sleep +// This is a funny workaround for the fact that "common.h" defines Sleep to be +// Dont_Use_Sleep, with the hope of causing linker errors whenever someone tries to use sleep. +// +// However, GCToOSInterface defines a function called Sleep, which (due to this define) becomes +// "Dont_Use_Sleep", which the GC in turn happily uses. The symbol that GCToOSInterface actually +// exported was called "GCToOSInterface::Dont_Use_Sleep". While we progress in making the GC standalone, +// we'll need to break the dependency on common.h (the VM header) and this problem will become moot. +#undef Sleep +#endif // Sleep + #ifdef HAS_SYSTEM_YIELDPROCESSOR // YieldProcessor is defined to Dont_Use_YieldProcessor. Restore it to the system-default implementation for the GC. #undef YieldProcessor diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 1021d669b2dc3..ec96a2e6fb65d 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -44526,25 +44526,9 @@ Object * GCHeap::NextObj (Object * object) return NULL; } - if (nextobj < heap_segment_mem (hs)) - { - return NULL; - } - - uint8_t* saved_alloc_allocated = hp->alloc_allocated; - heap_segment* saved_ephemeral_heap_segment = hp->ephemeral_heap_segment; - - // We still want to verify nextobj that lands between heap_segment_allocated and alloc_allocated - // on the ephemeral segment. In regions these 2 could be changed by another thread so we need - // to make sure they are still in sync by the time we check. If they are not in sync, we just - // bail which means we don't validate the next object during that small window and that's fine. - // - // We also miss validating nextobj if it's in the segment that just turned into the new ephemeral - // segment since we saved which is also a very small window and again that's fine. - if ((nextobj >= heap_segment_allocated (hs)) && - ((hs != saved_ephemeral_heap_segment) || - !in_range_for_segment(saved_alloc_allocated, saved_ephemeral_heap_segment) || - (nextobj >= saved_alloc_allocated))) + if ((nextobj < heap_segment_mem(hs)) || + (nextobj >= heap_segment_allocated(hs) && hs != hp->ephemeral_heap_segment) || + (nextobj >= hp->alloc_allocated)) { return NULL; } diff --git a/src/coreclr/gc/unix/cgroup.cpp b/src/coreclr/gc/unix/cgroup.cpp index 50069e469147e..34f7f4f47f62d 100644 --- a/src/coreclr/gc/unix/cgroup.cpp +++ b/src/coreclr/gc/unix/cgroup.cpp @@ -47,10 +47,6 @@ Module Name: #define CGROUP1_MEMORY_LIMIT_FILENAME "/memory.limit_in_bytes" #define CGROUP2_MEMORY_LIMIT_FILENAME "/memory.max" #define CGROUP_MEMORY_STAT_FILENAME "/memory.stat" -#define CGROUP1_MEMORY_USAGE_FILENAME "/memory.usage_in_bytes" -#define CGROUP2_MEMORY_USAGE_FILENAME "/memory.current" -#define CGROUP1_MEMORY_STAT_INACTIVE_FIELD "total_inactive_file " -#define CGROUP2_MEMORY_STAT_INACTIVE_FIELD "inactive_file " extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val); @@ -60,11 +56,36 @@ class CGroup static int s_cgroup_version; static char *s_memory_cgroup_path; + + static const char *s_mem_stat_key_names[]; + static size_t s_mem_stat_key_lengths[]; + static size_t s_mem_stat_n_keys; public: static void Initialize() { s_cgroup_version = FindCGroupVersion(); s_memory_cgroup_path = FindCGroupPath(s_cgroup_version == 1 ? &IsCGroup1MemorySubsystem : nullptr); + + if (s_cgroup_version == 1) + { + s_mem_stat_n_keys = 4; + s_mem_stat_key_names[0] = "total_inactive_anon "; + s_mem_stat_key_names[1] = "total_active_anon "; + s_mem_stat_key_names[2] = "total_dirty "; + s_mem_stat_key_names[3] = "total_unevictable "; + } + else + { + s_mem_stat_n_keys = 3; + s_mem_stat_key_names[0] = "anon "; + s_mem_stat_key_names[1] = "file_dirty "; + s_mem_stat_key_names[2] = "unevictable "; + } + + for (size_t i = 0; i < s_mem_stat_n_keys; i++) + { + s_mem_stat_key_lengths[i] = strlen(s_mem_stat_key_names[i]); + } } static void Cleanup() @@ -92,9 +113,9 @@ class CGroup if (s_cgroup_version == 0) return false; else if (s_cgroup_version == 1) - return GetCGroupMemoryUsage(val, CGROUP1_MEMORY_USAGE_FILENAME, CGROUP1_MEMORY_STAT_INACTIVE_FIELD); + return GetCGroupMemoryUsage(val); else if (s_cgroup_version == 2) - return GetCGroupMemoryUsage(val, CGROUP2_MEMORY_USAGE_FILENAME, CGROUP2_MEMORY_STAT_INACTIVE_FIELD); + return GetCGroupMemoryUsage(val); else { assert(!"Unknown cgroup version."); @@ -380,38 +401,8 @@ class CGroup return result; } - static bool GetCGroupMemoryUsage(size_t *val, const char *filename, const char *inactiveFileFieldName) + static bool GetCGroupMemoryUsage(size_t *val) { - // Use the same way to calculate memory load as popular container tools (Docker, Kubernetes, Containerd etc.) - // For cgroup v1: value of 'memory.usage_in_bytes' minus 'total_inactive_file' value of 'memory.stat' - // For cgroup v2: value of 'memory.current' minus 'inactive_file' value of 'memory.stat' - - char* mem_usage_filename = nullptr; - if (asprintf(&mem_usage_filename, "%s%s", s_memory_cgroup_path, filename) < 0) - return false; - - uint64_t temp = 0; - - size_t usage = 0; - - bool result = ReadMemoryValueFromFile(mem_usage_filename, &temp); - if (result) - { - if (temp > std::numeric_limits::max()) - { - usage = std::numeric_limits::max(); - } - else - { - usage = (size_t)temp; - } - } - - free(mem_usage_filename); - - if (!result) - return result; - if (s_memory_cgroup_path == nullptr) return false; @@ -426,38 +417,44 @@ class CGroup char *line = nullptr; size_t lineLen = 0; - bool foundInactiveFileValue = false; + size_t readValues = 0; char* endptr; - size_t inactiveFileFieldNameLength = strlen(inactiveFileFieldName); - - while (getline(&line, &lineLen, stat_file) != -1) + *val = 0; + while (getline(&line, &lineLen, stat_file) != -1 && readValues < s_mem_stat_n_keys) { - if (strncmp(line, inactiveFileFieldName, inactiveFileFieldNameLength) == 0) + for (size_t i = 0; i < s_mem_stat_n_keys; i++) { - errno = 0; - const char* startptr = line + inactiveFileFieldNameLength; - size_t inactiveFileValue = strtoll(startptr, &endptr, 10); - if (endptr != startptr && errno == 0) + if (strncmp(line, s_mem_stat_key_names[i], s_mem_stat_key_lengths[i]) == 0) { - foundInactiveFileValue = true; - *val = usage - inactiveFileValue; - } + errno = 0; + const char* startptr = line + s_mem_stat_key_lengths[i]; + *val += strtoll(startptr, &endptr, 10); + if (endptr != startptr && errno == 0) + readValues++; - break; + break; + } } } fclose(stat_file); free(line); - return foundInactiveFileValue; + if (readValues == s_mem_stat_n_keys) + return true; + + return false; } }; int CGroup::s_cgroup_version = 0; char *CGroup::s_memory_cgroup_path = nullptr; +const char *CGroup::s_mem_stat_key_names[4] = {}; +size_t CGroup::s_mem_stat_key_lengths[4] = {}; +size_t CGroup::s_mem_stat_n_keys = 0; + void InitializeCGroup() { CGroup::Initialize(); diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 4ad5f4b3795e8..8b536ad9dd7d8 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -876,29 +876,21 @@ bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) return result; } -#define UPDATE_CACHE_SIZE_AND_LEVEL(CACHE_LEVEL) if (size > cacheSize) { cacheSize = size; cacheLevel = CACHE_LEVEL; } - static size_t GetLogicalProcessorCacheSizeFromOS() { - size_t cacheLevel = 0; size_t cacheSize = 0; - size_t size; #ifdef _SC_LEVEL1_DCACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL1_DCACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(1) + cacheSize = std::max(cacheSize, ( size_t) sysconf(_SC_LEVEL1_DCACHE_SIZE)); #endif #ifdef _SC_LEVEL2_CACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL2_CACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(2) + cacheSize = std::max(cacheSize, ( size_t) sysconf(_SC_LEVEL2_CACHE_SIZE)); #endif #ifdef _SC_LEVEL3_CACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL3_CACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(3) + cacheSize = std::max(cacheSize, ( size_t) sysconf(_SC_LEVEL3_CACHE_SIZE)); #endif #ifdef _SC_LEVEL4_CACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL4_CACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(4) + cacheSize = std::max(cacheSize, ( size_t) sysconf(_SC_LEVEL4_CACHE_SIZE)); #endif #if defined(TARGET_LINUX) && !defined(HOST_ARM) && !defined(HOST_X86) @@ -909,39 +901,25 @@ static size_t GetLogicalProcessorCacheSizeFromOS() // for the platform. Currently musl and arm64 should be only cases to use // this method to determine cache size. // - size_t level; - char path_to_size_file[] = "/sys/devices/system/cpu/cpu0/cache/index-/size"; - char path_to_level_file[] = "/sys/devices/system/cpu/cpu0/cache/index-/level"; - int index = 40; - assert(path_to_size_file[index] == '-'); - assert(path_to_level_file[index] == '-'); - - for (int i = 0; i < 5; i++) - { - path_to_size_file[index] = (char)(48 + i); - - if (ReadMemoryValueFromFile(path_to_size_file, &size)) - { - path_to_level_file[index] = (char)(48 + i); - - if (ReadMemoryValueFromFile(path_to_level_file, &level)) - { - UPDATE_CACHE_SIZE_AND_LEVEL(level) - } - else - { - cacheSize = std::max(cacheSize, size); - } - } - } + size_t size; + + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index0/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index1/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index2/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index3/size", &size)) + cacheSize = std::max(cacheSize, size); + if (ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index4/size", &size)) + cacheSize = std::max(cacheSize, size); } #endif -#if (defined(HOST_ARM64) || defined(HOST_LOONGARCH64)) && !defined(TARGET_OSX) +#if defined(HOST_ARM64) && !defined(TARGET_OSX) if (cacheSize == 0) { - // We expect to get the L3 cache size for Arm64 but currently expected to be missing that info - // from most of the machines. + // It is currently expected to be missing cache size info // // _SC_LEVEL*_*CACHE_SIZE is not yet present. Work is in progress to enable this for arm64 // @@ -986,38 +964,6 @@ static size_t GetLogicalProcessorCacheSizeFromOS() } #endif -#if (defined(HOST_ARM64) || defined(HOST_LOONGARCH64)) && !defined(TARGET_OSX) - if (cacheLevel != 3) - { - // We expect to get the L3 cache size for Arm64 but currently expected to be missing that info - // from most of the machines. - // Hence, just use the following heuristics at best depending on the CPU count - // 1 ~ 4 : 4 MB - // 5 ~ 16 : 8 MB - // 17 ~ 64 : 16 MB - // 65+ : 32 MB - DWORD logicalCPUs = g_totalCpuCount; - if (logicalCPUs < 5) - { - cacheSize = 4; - } - else if (logicalCPUs < 17) - { - cacheSize = 8; - } - else if (logicalCPUs < 65) - { - cacheSize = 16; - } - else - { - cacheSize = 32; - } - - cacheSize *= (1024 * 1024); - } -#endif - return cacheSize; } @@ -1091,10 +1037,15 @@ size_t GCToOSInterface::GetCacheSizePerLogicalCpu(bool trueSize) size_t maxSize, maxTrueSize; maxSize = maxTrueSize = GetLogicalProcessorCacheSizeFromOS(); // Returns the size of the highest level processor cache +#if defined(HOST_ARM64) + // Bigger gen0 size helps arm64 targets + maxSize = maxTrueSize * 3; +#endif + s_maxSize = maxSize; s_maxTrueSize = maxTrueSize; - // printf("GetCacheSizePerLogicalCpu returns %zu, adjusted size %zu\n", maxSize, maxTrueSize); + // printf("GetCacheSizePerLogicalCpu returns %d, adjusted size %d\n", maxSize, maxTrueSize); return trueSize ? maxTrueSize : maxSize; } diff --git a/src/coreclr/gc/windows/gcenv.windows.cpp b/src/coreclr/gc/windows/gcenv.windows.cpp index ca7cc4132e5ee..8bb35badd6c2f 100644 --- a/src/coreclr/gc/windows/gcenv.windows.cpp +++ b/src/coreclr/gc/windows/gcenv.windows.cpp @@ -402,8 +402,6 @@ SYSTEM_LOGICAL_PROCESSOR_INFORMATION *GetLPI(PDWORD nEntries) size_t GetLogicalProcessorCacheSizeFromOS() { size_t cache_size = 0; - size_t cache_level = 0; - DWORD nEntries = 0; // Try to use GetLogicalProcessorInformation API and get a valid pointer to the SLPI array if successful. Returns NULL @@ -426,11 +424,7 @@ size_t GetLogicalProcessorCacheSizeFromOS() { if (pslpi[i].Relationship == RelationCache) { - if (last_cache_size < pslpi[i].Cache.Size) - { - last_cache_size = pslpi[i].Cache.Size; - cache_level = pslpi[i].Cache.Level; - } + last_cache_size = max(last_cache_size, pslpi[i].Cache.Size); } } cache_size = last_cache_size; @@ -440,39 +434,6 @@ size_t GetLogicalProcessorCacheSizeFromOS() if(pslpi) delete[] pslpi; // release the memory allocated for the SLPI array. -#if defined(TARGET_ARM64) - if (cache_level != 3) - { - uint32_t totalCPUCount = GCToOSInterface::GetTotalProcessorCount(); - - // We expect to get the L3 cache size for Arm64 but currently expected to be missing that info - // from most of the machines. - // Hence, just use the following heuristics at best depending on the CPU count - // 1 ~ 4 : 4 MB - // 5 ~ 16 : 8 MB - // 17 ~ 64 : 16 MB - // 65+ : 32 MB - if (totalCPUCount < 5) - { - cache_size = 4; - } - else if (totalCPUCount < 17) - { - cache_size = 8; - } - else if (totalCPUCount < 65) - { - cache_size = 16; - } - else - { - cache_size = 32; - } - - cache_size *= (1024 * 1024); - } -#endif // TARGET_ARM64 - return cache_size; } @@ -875,10 +836,15 @@ size_t GCToOSInterface::GetCacheSizePerLogicalCpu(bool trueSize) maxSize = maxTrueSize = GetLogicalProcessorCacheSizeFromOS() ; // Returns the size of the highest level processor cache +#if defined(TARGET_ARM64) + // Bigger gen0 size helps arm64 targets + maxSize = maxTrueSize * 3; +#endif + s_maxSize = maxSize; s_maxTrueSize = maxTrueSize; - // printf("GetCacheSizePerLogicalCpu returns %zu, adjusted size %zu\n", maxSize, maxTrueSize); + // printf("GetCacheSizePerLogicalCpu returns %d, adjusted size %d\n", maxSize, maxTrueSize); return trueSize ? maxTrueSize : maxSize; } diff --git a/src/coreclr/ilasm/assembler.h b/src/coreclr/ilasm/assembler.h index 43ecddf2ea0b5..76f6787021fd3 100644 --- a/src/coreclr/ilasm/assembler.h +++ b/src/coreclr/ilasm/assembler.h @@ -53,6 +53,10 @@ #define dwUniBuf 16384 +#ifdef TARGET_UNIX +extern char *g_pszExeFile; +#endif + extern WCHAR wzUniBuf[]; // Unicode conversion global buffer (assem.cpp) class Class; diff --git a/src/coreclr/ilasm/main.cpp b/src/coreclr/ilasm/main.cpp index d6d6e9201b1bf..146e8640b3cb4 100644 --- a/src/coreclr/ilasm/main.cpp +++ b/src/coreclr/ilasm/main.cpp @@ -29,6 +29,9 @@ static DWORD g_dwSubsystem=(DWORD)-1,g_dwComImageFlags=(DWORD)-1,g_dwFileAlig static ULONGLONG g_stBaseAddress=0; static size_t g_stSizeOfStackReserve=0; extern unsigned int g_uConsoleCP; +#ifdef TARGET_UNIX +char * g_pszExeFile; +#endif void MakeTestFile(_In_ __nullterminated char* szFileName) { @@ -852,6 +855,7 @@ extern "C" int _cdecl wmain(int argc, _In_ WCHAR **argv) #ifdef TARGET_UNIX int main(int argc, char* str[]) { + g_pszExeFile = str[0]; if (0 != PAL_Initialize(argc, str)) { fprintf(stderr,"Error: Fail to PAL_Initialize\n"); diff --git a/src/coreclr/ildasm/dasm.cpp b/src/coreclr/ildasm/dasm.cpp index 9942397f9da6d..03999e3c61872 100644 --- a/src/coreclr/ildasm/dasm.cpp +++ b/src/coreclr/ildasm/dasm.cpp @@ -123,6 +123,7 @@ BOOL g_fCustomInstructionEncodingSystem = FALSE; COR_FIELD_OFFSET *g_rFieldOffset = NULL; ULONG g_cFieldsMax, g_cFieldOffsets; +char* g_pszExeFile; char g_szInputFile[MAX_FILENAME_LENGTH]; // in UTF-8 WCHAR g_wszFullInputFile[MAX_PATH + 1]; // in UTF-16 char g_szOutputFile[MAX_FILENAME_LENGTH]; // in UTF-8 diff --git a/src/coreclr/ildasm/windasm.cpp b/src/coreclr/ildasm/windasm.cpp index bf80bad26b6cf..6ef983bc583c5 100644 --- a/src/coreclr/ildasm/windasm.cpp +++ b/src/coreclr/ildasm/windasm.cpp @@ -55,6 +55,7 @@ extern char g_szAsmCodeIndent[]; extern DWORD g_Mode; +extern char* g_pszExeFile; extern char g_szInputFile[]; // in UTF-8 extern WCHAR g_wszFullInputFile[]; // in UTF-16 extern char g_szOutputFile[]; // in UTF-8 @@ -423,10 +424,37 @@ int ProcessOneArg(_In_ __nullterminated char* szArg, _Out_ char** ppszObjFileNam return 0; } -#ifdef HOST_WINDOWS -int ParseCmdLineW(int argc, _In_ __nullterminated wchar_t* argv[], _Out_ char** ppszObjFileName) +char* UTF8toANSI(_In_ __nullterminated char* szUTF) +{ + ULONG32 L = (ULONG32) strlen(szUTF)+16; + WCHAR* wzUnicode = new WCHAR[L]; + memset(wzUnicode,0,L*sizeof(WCHAR)); + WszMultiByteToWideChar(CP_UTF8,0,szUTF,-1,wzUnicode,L); + L <<= 2; + char* szANSI = new char[L]; + memset(szANSI,0,L); + WszWideCharToMultiByte(g_uConsoleCP,0,wzUnicode,-1,szANSI,L,NULL,NULL); + VDELETE(wzUnicode); + return szANSI; +} +char* ANSItoUTF8(_In_ __nullterminated char* szANSI) { - int ret=0; + ULONG32 L = (ULONG32) strlen(szANSI)+16; + WCHAR* wzUnicode = new WCHAR[L]; + memset(wzUnicode,0,L*sizeof(WCHAR)); + WszMultiByteToWideChar(g_uConsoleCP,0,szANSI,-1,wzUnicode,L); + L *= 3; + char* szUTF = new char[L]; + memset(szUTF,0,L); + WszWideCharToMultiByte(CP_UTF8,0,wzUnicode,-1,szUTF,L,NULL,NULL); + VDELETE(wzUnicode); + return szUTF; +} + +int ParseCmdLineW(_In_ __nullterminated WCHAR* wzCmdLine, _Out_ char** ppszObjFileName) +{ + int argc,ret=0; + LPWSTR* argv= SegmentCommandLine(wzCmdLine, (DWORD*)&argc); char* szArg = new char[2048]; for(int i=1; i < argc; i++) { @@ -437,32 +465,54 @@ int ParseCmdLineW(int argc, _In_ __nullterminated wchar_t* argv[], _Out_ char** VDELETE(szArg); return ret; } -#else -int ParseCmdLine(int argc, _In_ __nullterminated char* argv[], _Out_ char** ppszObjFileName) + +int ParseCmdLineA(_In_ __nullterminated char* szCmdLine, _Out_ char** ppszObjFileName) { - int ret = 0; - char* szArg = new char[2048]; - for (int i = 1; i < argc; i++) + if((szCmdLine == NULL)||(*szCmdLine == 0)) return 0; + + // ANSI to UTF-8 + char* szCmdLineUTF = ANSItoUTF8(szCmdLine); + + // Split into argv[] + int argc=0, ret = 0; + DynamicArray argv; + char* pch; + char* pchend; + bool bUnquoted = true; + + pch = szCmdLineUTF; + pchend = pch+strlen(szCmdLineUTF); + while(pch) { - if ((ret = ProcessOneArg(argv[i], ppszObjFileName)) != 0) break; + for(; *pch == ' '; pch++); // skip the blanks + argv[argc++] = pch; + for(; pch < pchend; pch++) + { + if(*pch == '"') bUnquoted = !bUnquoted; + else if((*pch == ' ')&&bUnquoted) break; + } + + if(pch < pchend) *pch++ = 0; + else break; } - VDELETE(szArg); + + for(int i=1; i < argc; i++) + { + if((ret = ProcessOneArg(argv[i],ppszObjFileName)) != 0) break; + } + VDELETE(szCmdLineUTF); return ret; } -#endif -#ifdef HOST_WINDOWS -int __cdecl wmain(int argc, wchar_t* argv[]) -#else -int main(int argc, char* argv[]) -#endif +int __cdecl main(int nCmdShow, char* lpCmdLine[]) { #if defined(TARGET_UNIX) - if (0 != PAL_Initialize(argc, argv)) + if (0 != PAL_Initialize(nCmdShow, lpCmdLine)) { printError(g_pFile, "Error: Fail to PAL_Initialize\n"); exit(1); } + g_pszExeFile = lpCmdLine[0]; #endif #ifdef HOST_WINDOWS @@ -502,12 +552,7 @@ int main(int argc, char* argv[]) g_hResources = WszGetModuleHandle(NULL); #endif - -#ifdef HOST_WINDOWS - iCommandLineParsed = ParseCmdLineW(argc, argv, &g_pszObjFileName); -#else - iCommandLineParsed = ParseCmdLine(argc, argv, &g_pszObjFileName); -#endif + iCommandLineParsed = ParseCmdLineW((wzCommandLine = GetCommandLineW()),&g_pszObjFileName); if(!g_fLimitedVisibility) { diff --git a/src/coreclr/inc/contxt.h b/src/coreclr/inc/contxt.h new file mode 100644 index 0000000000000..1611e7616f5d3 --- /dev/null +++ b/src/coreclr/inc/contxt.h @@ -0,0 +1,3471 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + +/* File created by MIDL compiler version 5.01.0164 */ +/* at Mon May 01 14:39:38 2000 + */ +/* Compiler settings for contxt.idl: + Os (OptLev=s), W1, Zp8, env=Win32, ms_ext, c_ext + error checks: allocation ref bounds_check enum stub_data +*/ +//@@MIDL_FILE_HEADING( ) + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 440 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __contxt_h__ +#define __contxt_h__ + +#ifdef __cplusplus +extern "C"{ +#endif + +/* Forward Declarations */ + +#ifndef __IEnumContextProps_FWD_DEFINED__ +#define __IEnumContextProps_FWD_DEFINED__ +typedef interface IEnumContextProps IEnumContextProps; +#endif /* __IEnumContextProps_FWD_DEFINED__ */ + + +#ifndef __IContext_FWD_DEFINED__ +#define __IContext_FWD_DEFINED__ +typedef interface IContext IContext; +#endif /* __IContext_FWD_DEFINED__ */ + + +#ifndef __IContextMarshaler_FWD_DEFINED__ +#define __IContextMarshaler_FWD_DEFINED__ +typedef interface IContextMarshaler IContextMarshaler; +#endif /* __IContextMarshaler_FWD_DEFINED__ */ + + +#ifndef __IObjContext_FWD_DEFINED__ +#define __IObjContext_FWD_DEFINED__ +typedef interface IObjContext IObjContext; +#endif /* __IObjContext_FWD_DEFINED__ */ + + +#ifndef __IGetContextId_FWD_DEFINED__ +#define __IGetContextId_FWD_DEFINED__ +typedef interface IGetContextId IGetContextId; +#endif /* __IGetContextId_FWD_DEFINED__ */ + + +#ifndef __IAggregator_FWD_DEFINED__ +#define __IAggregator_FWD_DEFINED__ +typedef interface IAggregator IAggregator; +#endif /* __IAggregator_FWD_DEFINED__ */ + + +#ifndef __ICall_FWD_DEFINED__ +#define __ICall_FWD_DEFINED__ +typedef interface ICall ICall; +#endif /* __ICall_FWD_DEFINED__ */ + + +#ifndef __IRpcCall_FWD_DEFINED__ +#define __IRpcCall_FWD_DEFINED__ +typedef interface IRpcCall IRpcCall; +#endif /* __IRpcCall_FWD_DEFINED__ */ + + +#ifndef __ICallInfo_FWD_DEFINED__ +#define __ICallInfo_FWD_DEFINED__ +typedef interface ICallInfo ICallInfo; +#endif /* __ICallInfo_FWD_DEFINED__ */ + + +#ifndef __IPolicy_FWD_DEFINED__ +#define __IPolicy_FWD_DEFINED__ +typedef interface IPolicy IPolicy; +#endif /* __IPolicy_FWD_DEFINED__ */ + + +#ifndef __IPolicyAsync_FWD_DEFINED__ +#define __IPolicyAsync_FWD_DEFINED__ +typedef interface IPolicyAsync IPolicyAsync; +#endif /* __IPolicyAsync_FWD_DEFINED__ */ + + +#ifndef __IPolicySet_FWD_DEFINED__ +#define __IPolicySet_FWD_DEFINED__ +typedef interface IPolicySet IPolicySet; +#endif /* __IPolicySet_FWD_DEFINED__ */ + + +#ifndef __IComObjIdentity_FWD_DEFINED__ +#define __IComObjIdentity_FWD_DEFINED__ +typedef interface IComObjIdentity IComObjIdentity; +#endif /* __IComObjIdentity_FWD_DEFINED__ */ + + +#ifndef __IPolicyMaker_FWD_DEFINED__ +#define __IPolicyMaker_FWD_DEFINED__ +typedef interface IPolicyMaker IPolicyMaker; +#endif /* __IPolicyMaker_FWD_DEFINED__ */ + + +#ifndef __IExceptionNotification_FWD_DEFINED__ +#define __IExceptionNotification_FWD_DEFINED__ +typedef interface IExceptionNotification IExceptionNotification; +#endif /* __IExceptionNotification_FWD_DEFINED__ */ + + +#ifndef __IMarshalEnvoy_FWD_DEFINED__ +#define __IMarshalEnvoy_FWD_DEFINED__ +typedef interface IMarshalEnvoy IMarshalEnvoy; +#endif /* __IMarshalEnvoy_FWD_DEFINED__ */ + + +#ifndef __IWrapperInfo_FWD_DEFINED__ +#define __IWrapperInfo_FWD_DEFINED__ +typedef interface IWrapperInfo IWrapperInfo; +#endif /* __IWrapperInfo_FWD_DEFINED__ */ + + +#ifndef __IComThreadingInfo_FWD_DEFINED__ +#define __IComThreadingInfo_FWD_DEFINED__ +typedef interface IComThreadingInfo IComThreadingInfo; +#endif /* __IComThreadingInfo_FWD_DEFINED__ */ + + +#ifndef __IComDispatchInfo_FWD_DEFINED__ +#define __IComDispatchInfo_FWD_DEFINED__ +typedef interface IComDispatchInfo IComDispatchInfo; +#endif /* __IComDispatchInfo_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "wtypes.h" +#include "objidl.h" + +void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void __RPC_FAR * ); + +/* interface __MIDL_itf_contxt_0000 */ +/* [local] */ + +enum tagCONTEXTEVENT + { CONTEXTEVENT_NONE = 0, + CONTEXTEVENT_CALL = 0x1, + CONTEXTEVENT_ENTER = 0x2, + CONTEXTEVENT_LEAVE = 0x4, + CONTEXTEVENT_RETURN = 0x8, + CONTEXTEVENT_CALLFILLBUFFER = 0x10, + CONTEXTEVENT_ENTERWITHBUFFER = 0x20, + CONTEXTEVENT_LEAVEFILLBUFFER = 0x40, + CONTEXTEVENT_RETURNWITHBUFFER = 0x80, + CONTEXTEVENT_BEGINCALL = 0x100, + CONTEXTEVENT_BEGINENTER = 0x200, + CONTEXTEVENT_BEGINLEAVE = 0x400, + CONTEXTEVENT_BEGINRETURN = 0x800, + CONTEXTEVENT_FINISHCALL = 0x1000, + CONTEXTEVENT_FINISHENTER = 0x2000, + CONTEXTEVENT_FINISHLEAVE = 0x4000, + CONTEXTEVENT_FINISHRETURN = 0x8000, + CONTEXTEVENT_BEGINCALLFILLBUFFER = 0x10000, + CONTEXTEVENT_BEGINENTERWITHBUFFER = 0x20000, + CONTEXTEVENT_FINISHLEAVEFILLBUFFER = 0x40000, + CONTEXTEVENT_FINISHRETURNWITHBUFFER = 0x80000, + CONTEXTEVENT_LEAVEEXCEPTION = 0x100000, + CONTEXTEVENT_LEAVEEXCEPTIONFILLBUFFER = 0x200000, + CONTEXTEVENT_RETURNEXCEPTION = 0x400000, + CONTEXTEVENT_RETURNEXCEPTIONWITHBUFFER = 0x800000, + CONTEXTEVENT_ADDREFPOLICY = 0x10000000, + CONTEXTEVENT_RELEASEPOLICY = 0x20000000 + }; +typedef DWORD ContextEvent; + + +enum tagCPFLAGS + { CPFLAG_NONE = 0, + CPFLAG_PROPAGATE = 0x1, + CPFLAG_EXPOSE = 0x2, + CPFLAG_ENVOY = 0x4, + CPFLAG_MONITORSTUB = 0x8, + CPFLAG_MONITORPROXY = 0x10, + CPFLAG_DONTCOMPARE = 0x20 + }; +typedef DWORD CPFLAGS; + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0000_v0_0_s_ifspec; + +#ifndef __IEnumContextProps_INTERFACE_DEFINED__ +#define __IEnumContextProps_INTERFACE_DEFINED__ + +/* interface IEnumContextProps */ +/* [unique][uuid][object] */ + +typedef /* [unique] */ IEnumContextProps __RPC_FAR *LPENUMCONTEXTPROPS; + + +EXTERN_C const IID IID_IEnumContextProps; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c1-0000-0000-C000-000000000046") + IEnumContextProps : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Next( + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, + /* [out] */ ULONG __RPC_FAR *pceltFetched) = 0; + + virtual HRESULT STDMETHODCALLTYPE Skip( + /* [in] */ ULONG celt) = 0; + + virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE Clone( + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps) = 0; + + virtual HRESULT STDMETHODCALLTYPE Count( + /* [out] */ ULONG __RPC_FAR *pcelt) = 0; + + }; + +#else /* C style interface */ + + typedef struct IEnumContextPropsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IEnumContextProps __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IEnumContextProps __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IEnumContextProps __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Next )( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, + /* [out] */ ULONG __RPC_FAR *pceltFetched); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Skip )( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Reset )( + IEnumContextProps __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )( + IEnumContextProps __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Count )( + IEnumContextProps __RPC_FAR * This, + /* [out] */ ULONG __RPC_FAR *pcelt); + + END_INTERFACE + } IEnumContextPropsVtbl; + + interface IEnumContextProps + { + CONST_VTBL struct IEnumContextPropsVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IEnumContextProps_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IEnumContextProps_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IEnumContextProps_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IEnumContextProps_Next(This,celt,pContextProperties,pceltFetched) \ + (This)->lpVtbl -> Next(This,celt,pContextProperties,pceltFetched) + +#define IEnumContextProps_Skip(This,celt) \ + (This)->lpVtbl -> Skip(This,celt) + +#define IEnumContextProps_Reset(This) \ + (This)->lpVtbl -> Reset(This) + +#define IEnumContextProps_Clone(This,ppEnumContextProps) \ + (This)->lpVtbl -> Clone(This,ppEnumContextProps) + +#define IEnumContextProps_Count(This,pcelt) \ + (This)->lpVtbl -> Count(This,pcelt) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Next_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt, + /* [length_is][size_is][out] */ ContextProperty __RPC_FAR *pContextProperties, + /* [out] */ ULONG __RPC_FAR *pceltFetched); + + +void __RPC_STUB IEnumContextProps_Next_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Skip_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [in] */ ULONG celt); + + +void __RPC_STUB IEnumContextProps_Skip_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Reset_Proxy( + IEnumContextProps __RPC_FAR * This); + + +void __RPC_STUB IEnumContextProps_Reset_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Clone_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + +void __RPC_STUB IEnumContextProps_Clone_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IEnumContextProps_Count_Proxy( + IEnumContextProps __RPC_FAR * This, + /* [out] */ ULONG __RPC_FAR *pcelt); + + +void __RPC_STUB IEnumContextProps_Count_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IEnumContextProps_INTERFACE_DEFINED__ */ + + +#ifndef __IContext_INTERFACE_DEFINED__ +#define __IContext_INTERFACE_DEFINED__ + +/* interface IContext */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IContext; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c0-0000-0000-C000-000000000046") + IContext : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetProperty( + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE RemoveProperty( + /* [in] */ REFGUID rPolicyId) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetProperty( + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnumContextProps( + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps) = 0; + + }; + +#else /* C style interface */ + + typedef struct IContextVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IContext __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IContext __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IContext __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rPolicyId); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( + IContext __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + END_INTERFACE + } IContextVtbl; + + interface IContext + { + CONST_VTBL struct IContextVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IContext_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IContext_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IContext_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IContext_SetProperty(This,rpolicyId,flags,pUnk) \ + (This)->lpVtbl -> SetProperty(This,rpolicyId,flags,pUnk) + +#define IContext_RemoveProperty(This,rPolicyId) \ + (This)->lpVtbl -> RemoveProperty(This,rPolicyId) + +#define IContext_GetProperty(This,rGuid,pFlags,ppUnk) \ + (This)->lpVtbl -> GetProperty(This,rGuid,pFlags,ppUnk) + +#define IContext_EnumContextProps(This,ppEnumContextProps) \ + (This)->lpVtbl -> EnumContextProps(This,ppEnumContextProps) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IContext_SetProperty_Proxy( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk); + + +void __RPC_STUB IContext_SetProperty_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContext_RemoveProperty_Proxy( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rPolicyId); + + +void __RPC_STUB IContext_RemoveProperty_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContext_GetProperty_Proxy( + IContext __RPC_FAR * This, + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + +void __RPC_STUB IContext_GetProperty_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContext_EnumContextProps_Proxy( + IContext __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + +void __RPC_STUB IContext_EnumContextProps_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IContext_INTERFACE_DEFINED__ */ + + +#ifndef __IContextMarshaler_INTERFACE_DEFINED__ +#define __IContextMarshaler_INTERFACE_DEFINED__ + +/* interface IContextMarshaler */ +/* [uuid][object][local] */ + +typedef /* [unique] */ IContextMarshaler __RPC_FAR *LPCTXMARSHALER; + + +EXTERN_C const IID IID_IContextMarshaler; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001D8-0000-0000-C000-000000000046") + IContextMarshaler : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetMarshalSizeMax( + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags, + /* [out] */ DWORD __RPC_FAR *pSize) = 0; + + virtual HRESULT STDMETHODCALLTYPE MarshalInterface( + /* [unique][in] */ IStream __RPC_FAR *pStm, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags) = 0; + + }; + +#else /* C style interface */ + + typedef struct IContextMarshalerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IContextMarshaler __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IContextMarshaler __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IContextMarshaler __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetMarshalSizeMax )( + IContextMarshaler __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags, + /* [out] */ DWORD __RPC_FAR *pSize); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalInterface )( + IContextMarshaler __RPC_FAR * This, + /* [unique][in] */ IStream __RPC_FAR *pStm, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags); + + END_INTERFACE + } IContextMarshalerVtbl; + + interface IContextMarshaler + { + CONST_VTBL struct IContextMarshalerVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IContextMarshaler_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IContextMarshaler_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IContextMarshaler_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IContextMarshaler_GetMarshalSizeMax(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pSize) \ + (This)->lpVtbl -> GetMarshalSizeMax(This,riid,pv,dwDestContext,pvDestContext,mshlflags,pSize) + +#define IContextMarshaler_MarshalInterface(This,pStm,riid,pv,dwDestContext,pvDestContext,mshlflags) \ + (This)->lpVtbl -> MarshalInterface(This,pStm,riid,pv,dwDestContext,pvDestContext,mshlflags) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IContextMarshaler_GetMarshalSizeMax_Proxy( + IContextMarshaler __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags, + /* [out] */ DWORD __RPC_FAR *pSize); + + +void __RPC_STUB IContextMarshaler_GetMarshalSizeMax_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IContextMarshaler_MarshalInterface_Proxy( + IContextMarshaler __RPC_FAR * This, + /* [unique][in] */ IStream __RPC_FAR *pStm, + /* [in] */ REFIID riid, + /* [unique][in] */ void __RPC_FAR *pv, + /* [in] */ DWORD dwDestContext, + /* [unique][in] */ void __RPC_FAR *pvDestContext, + /* [in] */ DWORD mshlflags); + + +void __RPC_STUB IContextMarshaler_MarshalInterface_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IContextMarshaler_INTERFACE_DEFINED__ */ + + +// Placing the following definition here rather than with the IObjContext stuff +// below is a temporary workaround to get around build problems where the system +// objidl.h now has a IObjContext section but has not made much public (all the +// interface methods are marked as reserved and the following typedef does not +// exist). Once the system objidl.h is updated again we can remove the entire +// section. +#ifndef __PFNCTXCALLBACK_HACK +#define __PFNCTXCALLBACK_HACK +typedef /* [ref] */ HRESULT ( __stdcall __RPC_FAR *PFNCTXCALLBACK )( + void __RPC_FAR *pParam); +#endif + +#ifndef __IObjContext_INTERFACE_DEFINED__ +#define __IObjContext_INTERFACE_DEFINED__ + +/* interface IObjContext */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IObjContext; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c6-0000-0000-C000-000000000046") + IObjContext : public IContext + { + public: + virtual HRESULT STDMETHODCALLTYPE Freeze( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE DoCallback( + /* [in] */ PFNCTXCALLBACK pfnCallback, + /* [in] */ void __RPC_FAR *pParam, + /* [in] */ REFIID riid, + /* [in] */ unsigned int iMethod) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContextMarshaler( + /* [in] */ IContextMarshaler __RPC_FAR *pICM) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContextMarshaler( + /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetContextFlags( + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClearContextFlags( + /* [in] */ DWORD dwFlags) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetContextFlags( + /* [out] */ DWORD __RPC_FAR *pdwFlags) = 0; + + }; + +#else /* C style interface */ + + typedef struct IObjContextVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IObjContext __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IObjContext __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IObjContext __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetProperty )( + IObjContext __RPC_FAR * This, + /* [in] */ REFGUID rpolicyId, + /* [in] */ CPFLAGS flags, + /* [in] */ IUnknown __RPC_FAR *pUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *RemoveProperty )( + IObjContext __RPC_FAR * This, + /* [in] */ REFGUID rPolicyId); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetProperty )( + IObjContext __RPC_FAR * This, + /* [in] */ REFGUID rGuid, + /* [out] */ CPFLAGS __RPC_FAR *pFlags, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnumContextProps )( + IObjContext __RPC_FAR * This, + /* [out] */ IEnumContextProps __RPC_FAR *__RPC_FAR *ppEnumContextProps); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( + IObjContext __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DoCallback )( + IObjContext __RPC_FAR * This, + /* [in] */ PFNCTXCALLBACK pfnCallback, + /* [in] */ void __RPC_FAR *pParam, + /* [in] */ REFIID riid, + /* [in] */ unsigned int iMethod); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextMarshaler )( + IObjContext __RPC_FAR * This, + /* [in] */ IContextMarshaler __RPC_FAR *pICM); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextMarshaler )( + IObjContext __RPC_FAR * This, + /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetContextFlags )( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ClearContextFlags )( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextFlags )( + IObjContext __RPC_FAR * This, + /* [out] */ DWORD __RPC_FAR *pdwFlags); + + END_INTERFACE + } IObjContextVtbl; + + interface IObjContext + { + CONST_VTBL struct IObjContextVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IObjContext_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IObjContext_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IObjContext_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IObjContext_SetProperty(This,rpolicyId,flags,pUnk) \ + (This)->lpVtbl -> SetProperty(This,rpolicyId,flags,pUnk) + +#define IObjContext_RemoveProperty(This,rPolicyId) \ + (This)->lpVtbl -> RemoveProperty(This,rPolicyId) + +#define IObjContext_GetProperty(This,rGuid,pFlags,ppUnk) \ + (This)->lpVtbl -> GetProperty(This,rGuid,pFlags,ppUnk) + +#define IObjContext_EnumContextProps(This,ppEnumContextProps) \ + (This)->lpVtbl -> EnumContextProps(This,ppEnumContextProps) + + +#define IObjContext_Freeze(This) \ + (This)->lpVtbl -> Freeze(This) + +#define IObjContext_DoCallback(This,pfnCallback,pParam,riid,iMethod) \ + (This)->lpVtbl -> DoCallback(This,pfnCallback,pParam,riid,iMethod) + +#define IObjContext_SetContextMarshaler(This,pICM) \ + (This)->lpVtbl -> SetContextMarshaler(This,pICM) + +#define IObjContext_GetContextMarshaler(This,pICM) \ + (This)->lpVtbl -> GetContextMarshaler(This,pICM) + +#define IObjContext_SetContextFlags(This,dwFlags) \ + (This)->lpVtbl -> SetContextFlags(This,dwFlags) + +#define IObjContext_ClearContextFlags(This,dwFlags) \ + (This)->lpVtbl -> ClearContextFlags(This,dwFlags) + +#define IObjContext_GetContextFlags(This,pdwFlags) \ + (This)->lpVtbl -> GetContextFlags(This,pdwFlags) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IObjContext_Freeze_Proxy( + IObjContext __RPC_FAR * This); + + +void __RPC_STUB IObjContext_Freeze_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_DoCallback_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ PFNCTXCALLBACK pfnCallback, + /* [in] */ void __RPC_FAR *pParam, + /* [in] */ REFIID riid, + /* [in] */ unsigned int iMethod); + + +void __RPC_STUB IObjContext_DoCallback_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_SetContextMarshaler_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ IContextMarshaler __RPC_FAR *pICM); + + +void __RPC_STUB IObjContext_SetContextMarshaler_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_GetContextMarshaler_Proxy( + IObjContext __RPC_FAR * This, + /* [out] */ IContextMarshaler __RPC_FAR *__RPC_FAR *pICM); + + +void __RPC_STUB IObjContext_GetContextMarshaler_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_SetContextFlags_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + +void __RPC_STUB IObjContext_SetContextFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_ClearContextFlags_Proxy( + IObjContext __RPC_FAR * This, + /* [in] */ DWORD dwFlags); + + +void __RPC_STUB IObjContext_ClearContextFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IObjContext_GetContextFlags_Proxy( + IObjContext __RPC_FAR * This, + /* [out] */ DWORD __RPC_FAR *pdwFlags); + + +void __RPC_STUB IObjContext_GetContextFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IObjContext_INTERFACE_DEFINED__ */ + + +#ifndef __IGetContextId_INTERFACE_DEFINED__ +#define __IGetContextId_INTERFACE_DEFINED__ + +/* interface IGetContextId */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IGetContextId; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001dd-0000-0000-C000-000000000046") + IGetContextId : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContextId( + /* [out] */ GUID __RPC_FAR *pguidCtxtId) = 0; + + }; + +#else /* C style interface */ + + typedef struct IGetContextIdVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IGetContextId __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IGetContextId __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IGetContextId __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetContextId )( + IGetContextId __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidCtxtId); + + END_INTERFACE + } IGetContextIdVtbl; + + interface IGetContextId + { + CONST_VTBL struct IGetContextIdVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IGetContextId_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IGetContextId_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IGetContextId_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IGetContextId_GetContextId(This,pguidCtxtId) \ + (This)->lpVtbl -> GetContextId(This,pguidCtxtId) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IGetContextId_GetContextId_Proxy( + IGetContextId __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidCtxtId); + + +void __RPC_STUB IGetContextId_GetContextId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IGetContextId_INTERFACE_DEFINED__ */ + + +#ifndef __IAggregator_INTERFACE_DEFINED__ +#define __IAggregator_INTERFACE_DEFINED__ + +/* interface IAggregator */ +/* [unique][uuid][object][local] */ + +typedef /* [unique] */ IAggregator __RPC_FAR *IAGGREGATOR; + + +EXTERN_C const IID IID_IAggregator; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d8-0000-0000-C000-000000000046") + IAggregator : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Aggregate( + /* [in] */ IUnknown __RPC_FAR *pInnerUnk) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAggregatorVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IAggregator __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IAggregator __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IAggregator __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Aggregate )( + IAggregator __RPC_FAR * This, + /* [in] */ IUnknown __RPC_FAR *pInnerUnk); + + END_INTERFACE + } IAggregatorVtbl; + + interface IAggregator + { + CONST_VTBL struct IAggregatorVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAggregator_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAggregator_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAggregator_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAggregator_Aggregate(This,pInnerUnk) \ + (This)->lpVtbl -> Aggregate(This,pInnerUnk) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IAggregator_Aggregate_Proxy( + IAggregator __RPC_FAR * This, + /* [in] */ IUnknown __RPC_FAR *pInnerUnk); + + +void __RPC_STUB IAggregator_Aggregate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAggregator_INTERFACE_DEFINED__ */ + + +#ifndef __ICall_INTERFACE_DEFINED__ +#define __ICall_INTERFACE_DEFINED__ + +/* interface ICall */ +/* [unique][uuid][object][local] */ + +typedef /* [unique] */ ICall __RPC_FAR *LPCALL; + + +EXTERN_C const IID IID_ICall; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d6-0000-0000-C000-000000000046") + ICall : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCallInfo( + /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, + /* [out] */ IID __RPC_FAR *piid, + /* [out] */ DWORD __RPC_FAR *pdwMethod, + /* [out] */ HRESULT __RPC_FAR *phr) = 0; + + virtual HRESULT STDMETHODCALLTYPE Nullify( + /* [in] */ HRESULT hr) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetServerHR( + /* [out] */ HRESULT __RPC_FAR *phr) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICallVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + ICall __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + ICall __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + ICall __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallInfo )( + ICall __RPC_FAR * This, + /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, + /* [out] */ IID __RPC_FAR *piid, + /* [out] */ DWORD __RPC_FAR *pdwMethod, + /* [out] */ HRESULT __RPC_FAR *phr); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Nullify )( + ICall __RPC_FAR * This, + /* [in] */ HRESULT hr); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetServerHR )( + ICall __RPC_FAR * This, + /* [out] */ HRESULT __RPC_FAR *phr); + + END_INTERFACE + } ICallVtbl; + + interface ICall + { + CONST_VTBL struct ICallVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICall_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICall_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICall_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICall_GetCallInfo(This,ppIdentity,piid,pdwMethod,phr) \ + (This)->lpVtbl -> GetCallInfo(This,ppIdentity,piid,pdwMethod,phr) + +#define ICall_Nullify(This,hr) \ + (This)->lpVtbl -> Nullify(This,hr) + +#define ICall_GetServerHR(This,phr) \ + (This)->lpVtbl -> GetServerHR(This,phr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICall_GetCallInfo_Proxy( + ICall __RPC_FAR * This, + /* [out] */ const void __RPC_FAR *__RPC_FAR *ppIdentity, + /* [out] */ IID __RPC_FAR *piid, + /* [out] */ DWORD __RPC_FAR *pdwMethod, + /* [out] */ HRESULT __RPC_FAR *phr); + + +void __RPC_STUB ICall_GetCallInfo_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICall_Nullify_Proxy( + ICall __RPC_FAR * This, + /* [in] */ HRESULT hr); + + +void __RPC_STUB ICall_Nullify_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE ICall_GetServerHR_Proxy( + ICall __RPC_FAR * This, + /* [out] */ HRESULT __RPC_FAR *phr); + + +void __RPC_STUB ICall_GetServerHR_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICall_INTERFACE_DEFINED__ */ + + +#ifndef __IRpcCall_INTERFACE_DEFINED__ +#define __IRpcCall_INTERFACE_DEFINED__ + +/* interface IRpcCall */ +/* [unique][uuid][object][local] */ + +typedef /* [unique] */ IRpcCall __RPC_FAR *LPRPCCALL; + + +EXTERN_C const IID IID_IRpcCall; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c5-0000-0000-C000-000000000046") + IRpcCall : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetRpcOleMessage( + /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage) = 0; + + }; + +#else /* C style interface */ + + typedef struct IRpcCallVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IRpcCall __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IRpcCall __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IRpcCall __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetRpcOleMessage )( + IRpcCall __RPC_FAR * This, + /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage); + + END_INTERFACE + } IRpcCallVtbl; + + interface IRpcCall + { + CONST_VTBL struct IRpcCallVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IRpcCall_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IRpcCall_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IRpcCall_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IRpcCall_GetRpcOleMessage(This,ppMessage) \ + (This)->lpVtbl -> GetRpcOleMessage(This,ppMessage) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IRpcCall_GetRpcOleMessage_Proxy( + IRpcCall __RPC_FAR * This, + /* [out] */ RPCOLEMESSAGE __RPC_FAR *__RPC_FAR *ppMessage); + + +void __RPC_STUB IRpcCall_GetRpcOleMessage_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IRpcCall_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_contxt_0083 */ +/* [local] */ + +typedef +enum _CALLSOURCE + { CALLSOURCE_CROSSAPT = 0, + CALLSOURCE_CROSSCTX = 1 + } CALLSOURCE; + + + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0083_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0083_v0_0_s_ifspec; + +#ifndef __ICallInfo_INTERFACE_DEFINED__ +#define __ICallInfo_INTERFACE_DEFINED__ + +/* interface ICallInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_ICallInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001dc-0000-0000-C000-000000000046") + ICallInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCallSource( + /* [out] */ CALLSOURCE __RPC_FAR *pCallSource) = 0; + + }; + +#else /* C style interface */ + + typedef struct ICallInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + ICallInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + ICallInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + ICallInfo __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCallSource )( + ICallInfo __RPC_FAR * This, + /* [out] */ CALLSOURCE __RPC_FAR *pCallSource); + + END_INTERFACE + } ICallInfoVtbl; + + interface ICallInfo + { + CONST_VTBL struct ICallInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICallInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define ICallInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define ICallInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define ICallInfo_GetCallSource(This,pCallSource) \ + (This)->lpVtbl -> GetCallSource(This,pCallSource) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE ICallInfo_GetCallSource_Proxy( + ICallInfo __RPC_FAR * This, + /* [out] */ CALLSOURCE __RPC_FAR *pCallSource); + + +void __RPC_STUB ICallInfo_GetCallSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __ICallInfo_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicy_INTERFACE_DEFINED__ +#define __IPolicy_INTERFACE_DEFINED__ + +/* interface IPolicy */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicy; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c2-0000-0000-C000-000000000046") + IPolicy : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE Call( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE Enter( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE Leave( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE Return( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE CallGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE CallFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnterWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE LeaveGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE LeaveFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReturnWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + virtual ULONG STDMETHODCALLTYPE AddRefPolicy( void) = 0; + + virtual ULONG STDMETHODCALLTYPE ReleasePolicy( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicy __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicy __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicy __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Call )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Enter )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Leave )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Return )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallGetSize )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CallFillBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnterWithBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveGetSize )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LeaveFillBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *ReturnWithBuffer )( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRefPolicy )( + IPolicy __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *ReleasePolicy )( + IPolicy __RPC_FAR * This); + + END_INTERFACE + } IPolicyVtbl; + + interface IPolicy + { + CONST_VTBL struct IPolicyVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicy_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicy_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicy_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicy_Call(This,pCall) \ + (This)->lpVtbl -> Call(This,pCall) + +#define IPolicy_Enter(This,pCall) \ + (This)->lpVtbl -> Enter(This,pCall) + +#define IPolicy_Leave(This,pCall) \ + (This)->lpVtbl -> Leave(This,pCall) + +#define IPolicy_Return(This,pCall) \ + (This)->lpVtbl -> Return(This,pCall) + +#define IPolicy_CallGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> CallGetSize(This,pCall,pcb) + +#define IPolicy_CallFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> CallFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicy_EnterWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> EnterWithBuffer(This,pCall,pvBuf,cb) + +#define IPolicy_LeaveGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> LeaveGetSize(This,pCall,pcb) + +#define IPolicy_LeaveFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> LeaveFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicy_ReturnWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> ReturnWithBuffer(This,pCall,pvBuf,cb) + +#define IPolicy_AddRefPolicy(This) \ + (This)->lpVtbl -> AddRefPolicy(This) + +#define IPolicy_ReleasePolicy(This) \ + (This)->lpVtbl -> ReleasePolicy(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicy_Call_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Call_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_Enter_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Enter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_Leave_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Leave_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_Return_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicy_Return_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_CallGetSize_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_CallGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_CallFillBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_CallFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_EnterWithBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicy_EnterWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_LeaveGetSize_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_LeaveGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_LeaveFillBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicy_LeaveFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicy_ReturnWithBuffer_Proxy( + IPolicy __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicy_ReturnWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +ULONG STDMETHODCALLTYPE IPolicy_AddRefPolicy_Proxy( + IPolicy __RPC_FAR * This); + + +void __RPC_STUB IPolicy_AddRefPolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +ULONG STDMETHODCALLTYPE IPolicy_ReleasePolicy_Proxy( + IPolicy __RPC_FAR * This); + + +void __RPC_STUB IPolicy_ReleasePolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicy_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicyAsync_INTERFACE_DEFINED__ +#define __IPolicyAsync_INTERFACE_DEFINED__ + +/* interface IPolicyAsync */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicyAsync; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001cd-0000-0000-C000-000000000046") + IPolicyAsync : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE BeginCallGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginCall( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginCallFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginEnter( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginEnterWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginLeave( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE BeginReturn( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishCall( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishEnter( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishLeaveGetSize( + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishLeave( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishLeaveFillBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishReturn( + /* [in] */ ICall __RPC_FAR *pCall) = 0; + + virtual HRESULT STDMETHODCALLTYPE FinishReturnWithBuffer( + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicyAsyncVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicyAsync __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicyAsync __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallGetSize )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCall )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginCallFillBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnter )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginEnterWithBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginLeave )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *BeginReturn )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishCall )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishEnter )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveGetSize )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeave )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishLeaveFillBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturn )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *FinishReturnWithBuffer )( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + END_INTERFACE + } IPolicyAsyncVtbl; + + interface IPolicyAsync + { + CONST_VTBL struct IPolicyAsyncVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicyAsync_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicyAsync_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicyAsync_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicyAsync_BeginCallGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> BeginCallGetSize(This,pCall,pcb) + +#define IPolicyAsync_BeginCall(This,pCall) \ + (This)->lpVtbl -> BeginCall(This,pCall) + +#define IPolicyAsync_BeginCallFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> BeginCallFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicyAsync_BeginEnter(This,pCall) \ + (This)->lpVtbl -> BeginEnter(This,pCall) + +#define IPolicyAsync_BeginEnterWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> BeginEnterWithBuffer(This,pCall,pvBuf,cb) + +#define IPolicyAsync_BeginLeave(This,pCall) \ + (This)->lpVtbl -> BeginLeave(This,pCall) + +#define IPolicyAsync_BeginReturn(This,pCall) \ + (This)->lpVtbl -> BeginReturn(This,pCall) + +#define IPolicyAsync_FinishCall(This,pCall) \ + (This)->lpVtbl -> FinishCall(This,pCall) + +#define IPolicyAsync_FinishEnter(This,pCall) \ + (This)->lpVtbl -> FinishEnter(This,pCall) + +#define IPolicyAsync_FinishLeaveGetSize(This,pCall,pcb) \ + (This)->lpVtbl -> FinishLeaveGetSize(This,pCall,pcb) + +#define IPolicyAsync_FinishLeave(This,pCall) \ + (This)->lpVtbl -> FinishLeave(This,pCall) + +#define IPolicyAsync_FinishLeaveFillBuffer(This,pCall,pvBuf,pcb) \ + (This)->lpVtbl -> FinishLeaveFillBuffer(This,pCall,pvBuf,pcb) + +#define IPolicyAsync_FinishReturn(This,pCall) \ + (This)->lpVtbl -> FinishReturn(This,pCall) + +#define IPolicyAsync_FinishReturnWithBuffer(This,pCall,pvBuf,cb) \ + (This)->lpVtbl -> FinishReturnWithBuffer(This,pCall,pvBuf,cb) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallGetSize_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_BeginCallGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCall_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginCall_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginCallFillBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_BeginCallFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnter_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginEnter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginEnterWithBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicyAsync_BeginEnterWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginLeave_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginLeave_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_BeginReturn_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_BeginReturn_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishCall_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishCall_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishEnter_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishEnter_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveGetSize_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_FinishLeaveGetSize_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeave_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishLeave_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishLeaveFillBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [out] */ ULONG __RPC_FAR *pcb); + + +void __RPC_STUB IPolicyAsync_FinishLeaveFillBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturn_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall); + + +void __RPC_STUB IPolicyAsync_FinishReturn_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyAsync_FinishReturnWithBuffer_Proxy( + IPolicyAsync __RPC_FAR * This, + /* [in] */ ICall __RPC_FAR *pCall, + /* [in] */ void __RPC_FAR *pvBuf, + /* [in] */ ULONG cb); + + +void __RPC_STUB IPolicyAsync_FinishReturnWithBuffer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicyAsync_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicySet_INTERFACE_DEFINED__ +#define __IPolicySet_INTERFACE_DEFINED__ + +/* interface IPolicySet */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicySet; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c3-0000-0000-C000-000000000046") + IPolicySet : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddPolicy( + /* [in] */ ContextEvent ctxEvent, + /* [in] */ REFGUID rguid, + /* [in] */ IPolicy __RPC_FAR *pPolicy) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicySetVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicySet __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicySet __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicySet __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddPolicy )( + IPolicySet __RPC_FAR * This, + /* [in] */ ContextEvent ctxEvent, + /* [in] */ REFGUID rguid, + /* [in] */ IPolicy __RPC_FAR *pPolicy); + + END_INTERFACE + } IPolicySetVtbl; + + interface IPolicySet + { + CONST_VTBL struct IPolicySetVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicySet_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicySet_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicySet_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicySet_AddPolicy(This,ctxEvent,rguid,pPolicy) \ + (This)->lpVtbl -> AddPolicy(This,ctxEvent,rguid,pPolicy) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicySet_AddPolicy_Proxy( + IPolicySet __RPC_FAR * This, + /* [in] */ ContextEvent ctxEvent, + /* [in] */ REFGUID rguid, + /* [in] */ IPolicy __RPC_FAR *pPolicy); + + +void __RPC_STUB IPolicySet_AddPolicy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicySet_INTERFACE_DEFINED__ */ + + +#ifndef __IComObjIdentity_INTERFACE_DEFINED__ +#define __IComObjIdentity_INTERFACE_DEFINED__ + +/* interface IComObjIdentity */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IComObjIdentity; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d7-0000-0000-C000-000000000046") + IComObjIdentity : public IUnknown + { + public: + virtual BOOL STDMETHODCALLTYPE IsServer( void) = 0; + + virtual BOOL STDMETHODCALLTYPE IsDeactivated( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetIdentity( + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk) = 0; + + }; + +#else /* C style interface */ + + typedef struct IComObjIdentityVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IComObjIdentity __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IComObjIdentity __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IComObjIdentity __RPC_FAR * This); + + BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsServer )( + IComObjIdentity __RPC_FAR * This); + + BOOL ( STDMETHODCALLTYPE __RPC_FAR *IsDeactivated )( + IComObjIdentity __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIdentity )( + IComObjIdentity __RPC_FAR * This, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + END_INTERFACE + } IComObjIdentityVtbl; + + interface IComObjIdentity + { + CONST_VTBL struct IComObjIdentityVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IComObjIdentity_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IComObjIdentity_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IComObjIdentity_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IComObjIdentity_IsServer(This) \ + (This)->lpVtbl -> IsServer(This) + +#define IComObjIdentity_IsDeactivated(This) \ + (This)->lpVtbl -> IsDeactivated(This) + +#define IComObjIdentity_GetIdentity(This,ppUnk) \ + (This)->lpVtbl -> GetIdentity(This,ppUnk) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +BOOL STDMETHODCALLTYPE IComObjIdentity_IsServer_Proxy( + IComObjIdentity __RPC_FAR * This); + + +void __RPC_STUB IComObjIdentity_IsServer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +BOOL STDMETHODCALLTYPE IComObjIdentity_IsDeactivated_Proxy( + IComObjIdentity __RPC_FAR * This); + + +void __RPC_STUB IComObjIdentity_IsDeactivated_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComObjIdentity_GetIdentity_Proxy( + IComObjIdentity __RPC_FAR * This, + /* [out] */ IUnknown __RPC_FAR *__RPC_FAR *ppUnk); + + +void __RPC_STUB IComObjIdentity_GetIdentity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IComObjIdentity_INTERFACE_DEFINED__ */ + + +#ifndef __IPolicyMaker_INTERFACE_DEFINED__ +#define __IPolicyMaker_INTERFACE_DEFINED__ + +/* interface IPolicyMaker */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IPolicyMaker; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c4-0000-0000-C000-000000000046") + IPolicyMaker : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddClientPoliciesToSet( + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddEnvoyPoliciesToSet( + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE AddServerPoliciesToSet( + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE Freeze( + /* [in] */ IObjContext __RPC_FAR *pObjContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateStub( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + virtual HRESULT STDMETHODCALLTYPE DestroyStub( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateProxy( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + virtual HRESULT STDMETHODCALLTYPE DestroyProxy( + /* [in] */ IComObjIdentity __RPC_FAR *pID) = 0; + + }; + +#else /* C style interface */ + + typedef struct IPolicyMakerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IPolicyMaker __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IPolicyMaker __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddClientPoliciesToSet )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddEnvoyPoliciesToSet )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *AddServerPoliciesToSet )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Freeze )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IObjContext __RPC_FAR *pObjContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateStub )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyStub )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateProxy )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DestroyProxy )( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + END_INTERFACE + } IPolicyMakerVtbl; + + interface IPolicyMaker + { + CONST_VTBL struct IPolicyMakerVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IPolicyMaker_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IPolicyMaker_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IPolicyMaker_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IPolicyMaker_AddClientPoliciesToSet(This,pPS,pClientContext,pServerContext) \ + (This)->lpVtbl -> AddClientPoliciesToSet(This,pPS,pClientContext,pServerContext) + +#define IPolicyMaker_AddEnvoyPoliciesToSet(This,pPS,pClientContext,pServerContext) \ + (This)->lpVtbl -> AddEnvoyPoliciesToSet(This,pPS,pClientContext,pServerContext) + +#define IPolicyMaker_AddServerPoliciesToSet(This,pPS,pClientContext,pServerContext) \ + (This)->lpVtbl -> AddServerPoliciesToSet(This,pPS,pClientContext,pServerContext) + +#define IPolicyMaker_Freeze(This,pObjContext) \ + (This)->lpVtbl -> Freeze(This,pObjContext) + +#define IPolicyMaker_CreateStub(This,pID) \ + (This)->lpVtbl -> CreateStub(This,pID) + +#define IPolicyMaker_DestroyStub(This,pID) \ + (This)->lpVtbl -> DestroyStub(This,pID) + +#define IPolicyMaker_CreateProxy(This,pID) \ + (This)->lpVtbl -> CreateProxy(This,pID) + +#define IPolicyMaker_DestroyProxy(This,pID) \ + (This)->lpVtbl -> DestroyProxy(This,pID) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddClientPoliciesToSet_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + +void __RPC_STUB IPolicyMaker_AddClientPoliciesToSet_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddEnvoyPoliciesToSet_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + +void __RPC_STUB IPolicyMaker_AddEnvoyPoliciesToSet_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_AddServerPoliciesToSet_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IPolicySet __RPC_FAR *pPS, + /* [in] */ IContext __RPC_FAR *pClientContext, + /* [in] */ IContext __RPC_FAR *pServerContext); + + +void __RPC_STUB IPolicyMaker_AddServerPoliciesToSet_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_Freeze_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IObjContext __RPC_FAR *pObjContext); + + +void __RPC_STUB IPolicyMaker_Freeze_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateStub_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_CreateStub_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyStub_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_DestroyStub_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_CreateProxy_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_CreateProxy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IPolicyMaker_DestroyProxy_Proxy( + IPolicyMaker __RPC_FAR * This, + /* [in] */ IComObjIdentity __RPC_FAR *pID); + + +void __RPC_STUB IPolicyMaker_DestroyProxy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IPolicyMaker_INTERFACE_DEFINED__ */ + + +#ifndef __IExceptionNotification_INTERFACE_DEFINED__ +#define __IExceptionNotification_INTERFACE_DEFINED__ + +/* interface IExceptionNotification */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IExceptionNotification; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001db-0000-0000-C000-000000000046") + IExceptionNotification : public IUnknown + { + public: + virtual void STDMETHODCALLTYPE ServerException( + /* [in] */ void __RPC_FAR *pExcepPtrs) = 0; + + }; + +#else /* C style interface */ + + typedef struct IExceptionNotificationVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IExceptionNotification __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IExceptionNotification __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IExceptionNotification __RPC_FAR * This); + + void ( STDMETHODCALLTYPE __RPC_FAR *ServerException )( + IExceptionNotification __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pExcepPtrs); + + END_INTERFACE + } IExceptionNotificationVtbl; + + interface IExceptionNotification + { + CONST_VTBL struct IExceptionNotificationVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IExceptionNotification_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IExceptionNotification_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IExceptionNotification_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IExceptionNotification_ServerException(This,pExcepPtrs) \ + (This)->lpVtbl -> ServerException(This,pExcepPtrs) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +void STDMETHODCALLTYPE IExceptionNotification_ServerException_Proxy( + IExceptionNotification __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pExcepPtrs); + + +void __RPC_STUB IExceptionNotification_ServerException_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IExceptionNotification_INTERFACE_DEFINED__ */ + + +#ifndef __IMarshalEnvoy_INTERFACE_DEFINED__ +#define __IMarshalEnvoy_INTERFACE_DEFINED__ + +/* interface IMarshalEnvoy */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IMarshalEnvoy; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001c8-0000-0000-C000-000000000046") + IMarshalEnvoy : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetEnvoyUnmarshalClass( + /* [in] */ DWORD dwDestContext, + /* [out] */ CLSID __RPC_FAR *pClsid) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEnvoySizeMax( + /* [in] */ DWORD dwDestContext, + /* [out] */ DWORD __RPC_FAR *pcb) = 0; + + virtual HRESULT STDMETHODCALLTYPE MarshalEnvoy( + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ DWORD dwDestContext) = 0; + + virtual HRESULT STDMETHODCALLTYPE UnmarshalEnvoy( + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk) = 0; + + }; + +#else /* C style interface */ + + typedef struct IMarshalEnvoyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IMarshalEnvoy __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IMarshalEnvoy __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoyUnmarshalClass )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ CLSID __RPC_FAR *pClsid); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetEnvoySizeMax )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ DWORD __RPC_FAR *pcb); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *MarshalEnvoy )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ DWORD dwDestContext); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *UnmarshalEnvoy )( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk); + + END_INTERFACE + } IMarshalEnvoyVtbl; + + interface IMarshalEnvoy + { + CONST_VTBL struct IMarshalEnvoyVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IMarshalEnvoy_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IMarshalEnvoy_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IMarshalEnvoy_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IMarshalEnvoy_GetEnvoyUnmarshalClass(This,dwDestContext,pClsid) \ + (This)->lpVtbl -> GetEnvoyUnmarshalClass(This,dwDestContext,pClsid) + +#define IMarshalEnvoy_GetEnvoySizeMax(This,dwDestContext,pcb) \ + (This)->lpVtbl -> GetEnvoySizeMax(This,dwDestContext,pcb) + +#define IMarshalEnvoy_MarshalEnvoy(This,pStream,dwDestContext) \ + (This)->lpVtbl -> MarshalEnvoy(This,pStream,dwDestContext) + +#define IMarshalEnvoy_UnmarshalEnvoy(This,pStream,riid,ppunk) \ + (This)->lpVtbl -> UnmarshalEnvoy(This,pStream,riid,ppunk) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoyUnmarshalClass_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ CLSID __RPC_FAR *pClsid); + + +void __RPC_STUB IMarshalEnvoy_GetEnvoyUnmarshalClass_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_GetEnvoySizeMax_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ DWORD dwDestContext, + /* [out] */ DWORD __RPC_FAR *pcb); + + +void __RPC_STUB IMarshalEnvoy_GetEnvoySizeMax_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_MarshalEnvoy_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ DWORD dwDestContext); + + +void __RPC_STUB IMarshalEnvoy_MarshalEnvoy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IMarshalEnvoy_UnmarshalEnvoy_Proxy( + IMarshalEnvoy __RPC_FAR * This, + /* [in] */ IStream __RPC_FAR *pStream, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppunk); + + +void __RPC_STUB IMarshalEnvoy_UnmarshalEnvoy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IMarshalEnvoy_INTERFACE_DEFINED__ */ + + +#ifndef __IWrapperInfo_INTERFACE_DEFINED__ +#define __IWrapperInfo_INTERFACE_DEFINED__ + +/* interface IWrapperInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IWrapperInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("5052f924-7ab8-11d3-b93f-00c04f990176") + IWrapperInfo : public IUnknown + { + public: + virtual void STDMETHODCALLTYPE SetMapping( + void __RPC_FAR *pv) = 0; + + virtual void __RPC_FAR *STDMETHODCALLTYPE GetMapping( void) = 0; + + virtual IObjContext __RPC_FAR *STDMETHODCALLTYPE GetServerObjectContext( void) = 0; + + virtual IUnknown __RPC_FAR *STDMETHODCALLTYPE GetServerObject( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IWrapperInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IWrapperInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IWrapperInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IWrapperInfo __RPC_FAR * This); + + void ( STDMETHODCALLTYPE __RPC_FAR *SetMapping )( + IWrapperInfo __RPC_FAR * This, + void __RPC_FAR *pv); + + void __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetMapping )( + IWrapperInfo __RPC_FAR * This); + + IObjContext __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObjectContext )( + IWrapperInfo __RPC_FAR * This); + + IUnknown __RPC_FAR *( STDMETHODCALLTYPE __RPC_FAR *GetServerObject )( + IWrapperInfo __RPC_FAR * This); + + END_INTERFACE + } IWrapperInfoVtbl; + + interface IWrapperInfo + { + CONST_VTBL struct IWrapperInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IWrapperInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IWrapperInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IWrapperInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IWrapperInfo_SetMapping(This,pv) \ + (This)->lpVtbl -> SetMapping(This,pv) + +#define IWrapperInfo_GetMapping(This) \ + (This)->lpVtbl -> GetMapping(This) + +#define IWrapperInfo_GetServerObjectContext(This) \ + (This)->lpVtbl -> GetServerObjectContext(This) + +#define IWrapperInfo_GetServerObject(This) \ + (This)->lpVtbl -> GetServerObject(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +void STDMETHODCALLTYPE IWrapperInfo_SetMapping_Proxy( + IWrapperInfo __RPC_FAR * This, + void __RPC_FAR *pv); + + +void __RPC_STUB IWrapperInfo_SetMapping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +void __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetMapping_Proxy( + IWrapperInfo __RPC_FAR * This); + + +void __RPC_STUB IWrapperInfo_GetMapping_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +IObjContext __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObjectContext_Proxy( + IWrapperInfo __RPC_FAR * This); + + +void __RPC_STUB IWrapperInfo_GetServerObjectContext_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +IUnknown __RPC_FAR *STDMETHODCALLTYPE IWrapperInfo_GetServerObject_Proxy( + IWrapperInfo __RPC_FAR * This); + + +void __RPC_STUB IWrapperInfo_GetServerObject_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IWrapperInfo_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_contxt_0092 */ +/* [local] */ + + +typedef DWORD APARTMENTID; + + + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0092_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0092_v0_0_s_ifspec; + +#ifndef __IComThreadingInfo_INTERFACE_DEFINED__ +#define __IComThreadingInfo_INTERFACE_DEFINED__ + +/* interface IComThreadingInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IComThreadingInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001ce-0000-0000-C000-000000000046") + IComThreadingInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetCurrentApartmentType( + /* [out] */ APTTYPE __RPC_FAR *pAptType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadType( + /* [out] */ THDTYPE __RPC_FAR *pThreadType) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetCurrentLogicalThreadId( + /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetCurrentLogicalThreadId( + /* [in] */ REFGUID rguid) = 0; + + }; + +#else /* C style interface */ + + typedef struct IComThreadingInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IComThreadingInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IComThreadingInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IComThreadingInfo __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentApartmentType )( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ APTTYPE __RPC_FAR *pAptType); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentThreadType )( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ THDTYPE __RPC_FAR *pThreadType); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetCurrentLogicalThreadId )( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetCurrentLogicalThreadId )( + IComThreadingInfo __RPC_FAR * This, + /* [in] */ REFGUID rguid); + + END_INTERFACE + } IComThreadingInfoVtbl; + + interface IComThreadingInfo + { + CONST_VTBL struct IComThreadingInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IComThreadingInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IComThreadingInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IComThreadingInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IComThreadingInfo_GetCurrentApartmentType(This,pAptType) \ + (This)->lpVtbl -> GetCurrentApartmentType(This,pAptType) + +#define IComThreadingInfo_GetCurrentThreadType(This,pThreadType) \ + (This)->lpVtbl -> GetCurrentThreadType(This,pThreadType) + +#define IComThreadingInfo_GetCurrentLogicalThreadId(This,pguidLogicalThreadId) \ + (This)->lpVtbl -> GetCurrentLogicalThreadId(This,pguidLogicalThreadId) + +#define IComThreadingInfo_SetCurrentLogicalThreadId(This,rguid) \ + (This)->lpVtbl -> SetCurrentLogicalThreadId(This,rguid) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentApartmentType_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ APTTYPE __RPC_FAR *pAptType); + + +void __RPC_STUB IComThreadingInfo_GetCurrentApartmentType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentThreadType_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ THDTYPE __RPC_FAR *pThreadType); + + +void __RPC_STUB IComThreadingInfo_GetCurrentThreadType_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_GetCurrentLogicalThreadId_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [out] */ GUID __RPC_FAR *pguidLogicalThreadId); + + +void __RPC_STUB IComThreadingInfo_GetCurrentLogicalThreadId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComThreadingInfo_SetCurrentLogicalThreadId_Proxy( + IComThreadingInfo __RPC_FAR * This, + /* [in] */ REFGUID rguid); + + +void __RPC_STUB IComThreadingInfo_SetCurrentLogicalThreadId_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IComThreadingInfo_INTERFACE_DEFINED__ */ + + +#ifndef __IComDispatchInfo_INTERFACE_DEFINED__ +#define __IComDispatchInfo_INTERFACE_DEFINED__ + +/* interface IComDispatchInfo */ +/* [unique][uuid][object][local] */ + + +EXTERN_C const IID IID_IComDispatchInfo; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("000001d9-0000-0000-C000-000000000046") + IComDispatchInfo : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE EnableComInits( + /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie) = 0; + + virtual HRESULT STDMETHODCALLTYPE DisableComInits( + /* [in] */ void __RPC_FAR *pvCookie) = 0; + + }; + +#else /* C style interface */ + + typedef struct IComDispatchInfoVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( + IComDispatchInfo __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( + IComDispatchInfo __RPC_FAR * This); + + ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( + IComDispatchInfo __RPC_FAR * This); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *EnableComInits )( + IComDispatchInfo __RPC_FAR * This, + /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie); + + HRESULT ( STDMETHODCALLTYPE __RPC_FAR *DisableComInits )( + IComDispatchInfo __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pvCookie); + + END_INTERFACE + } IComDispatchInfoVtbl; + + interface IComDispatchInfo + { + CONST_VTBL struct IComDispatchInfoVtbl __RPC_FAR *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IComDispatchInfo_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IComDispatchInfo_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IComDispatchInfo_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IComDispatchInfo_EnableComInits(This,ppvCookie) \ + (This)->lpVtbl -> EnableComInits(This,ppvCookie) + +#define IComDispatchInfo_DisableComInits(This,pvCookie) \ + (This)->lpVtbl -> DisableComInits(This,pvCookie) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IComDispatchInfo_EnableComInits_Proxy( + IComDispatchInfo __RPC_FAR * This, + /* [out] */ void __RPC_FAR *__RPC_FAR *ppvCookie); + + +void __RPC_STUB IComDispatchInfo_EnableComInits_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IComDispatchInfo_DisableComInits_Proxy( + IComDispatchInfo __RPC_FAR * This, + /* [in] */ void __RPC_FAR *pvCookie); + + +void __RPC_STUB IComDispatchInfo_DisableComInits_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IComDispatchInfo_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_contxt_0094 */ +/* [local] */ + +typedef DWORD HActivator; + +STDAPI CoCreateObjectInContext(IUnknown *pUnk, IObjContext *pObjectCtx, REFIID riid, void **ppv); +STDAPI CoGetApartmentID(APTTYPE dAptType, HActivator* pAptID); +STDAPI CoDeactivateObject(IUnknown *pUnk, IUnknown **ppCookie); +STDAPI CoReactivateObject(IUnknown *pUnk, IUnknown *pCookie); +#define MSHLFLAGS_NO_IEC 0x8 // don't use IExternalConnextion +#define MSHLFLAGS_NO_IMARSHAL 0x10 // don't use IMarshal +#define CONTEXTFLAGS_FROZEN 0x01 // Frozen context +#define CONTEXTFLAGS_ALLOWUNAUTH 0x02 // Allow unauthenticated calls +#define CONTEXTFLAGS_ENVOYCONTEXT 0x04 // Envoy context +#define CONTEXTFLAGS_DEFAULTCONTEXT 0x08 // Default context +#define CONTEXTFLAGS_STATICCONTEXT 0x10 // Static context +#define CONTEXTFLAGS_INPROPTABLE 0x20 // Is in property table +#define CONTEXTFLAGS_INDESTRUCTOR 0x40 // Is in destructor +#define CONTEXTFLAGS_URTPROPPRESENT 0x80 // CLR property added + + +extern RPC_IF_HANDLE __MIDL_itf_contxt_0094_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_contxt_0094_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/coreclr/inc/corhlprpriv.h b/src/coreclr/inc/corhlprpriv.h index 2c8372860ba2e..38faa6f6ef8be 100644 --- a/src/coreclr/inc/corhlprpriv.h +++ b/src/coreclr/inc/corhlprpriv.h @@ -605,7 +605,7 @@ class RidBitmap HRESULT hr = S_OK; mdToken rid = RidFromToken(token); SIZE_T index = rid / 8; - BYTE bit = (BYTE)(1 << (rid % 8)); + BYTE bit = (1 << (rid % 8)); if (index >= buffer.Size()) { @@ -623,7 +623,7 @@ class RidBitmap { mdToken rid = RidFromToken(token); SIZE_T index = rid / 8; - BYTE bit = (BYTE)(1 << (rid % 8)); + BYTE bit = (1 << (rid % 8)); return ((index < buffer.Size()) && (buffer[index] & bit)); } diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 91c5734c90588..7a673e52d7cc7 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -640,14 +640,9 @@ enum CorInfoHelpFunc CORINFO_HELP_STACK_PROBE, // Probes each page of the allocated stack frame CORINFO_HELP_PATCHPOINT, // Notify runtime that code has reached a patchpoint - CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, // Notify runtime that code has reached a part of the method that wasn't originally jitted. - CORINFO_HELP_CLASSPROFILE32, // Update 32-bit class profile for a call site CORINFO_HELP_CLASSPROFILE64, // Update 64-bit class profile for a call site - CORINFO_HELP_DELEGATEPROFILE32, // Update 32-bit method profile for a delegate call site - CORINFO_HELP_DELEGATEPROFILE64, // Update 64-bit method profile for a delegate call site - CORINFO_HELP_VTABLEPROFILE32, // Update 32-bit method profile for a vtable call site - CORINFO_HELP_VTABLEPROFILE64, // Update 64-bit method profile for a vtable call site + CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, // Notify runtime that code has reached a part of the method that wasn't originally jitted. CORINFO_HELP_VALIDATE_INDIRECT_CALL, // CFG: Validate function pointer CORINFO_HELP_DISPATCH_INDIRECT_CALL, // CFG: Validate and dispatch to pointer @@ -959,14 +954,11 @@ enum CorInfoClassId enum CorInfoInline { - INLINE_PASS = 0, // Inlining OK - INLINE_PREJIT_SUCCESS = 1, // Inline check for prejit checking usage succeeded - INLINE_CHECK_CAN_INLINE_SUCCESS = 2, // JIT detected it is permitted to try to actually inline - INLINE_CHECK_CAN_INLINE_VMFAIL = 3, // VM specified that inline must fail via the CanInline api + INLINE_PASS = 0, // Inlining OK // failures are negative - INLINE_FAIL = -1, // Inlining not OK for this case only - INLINE_NEVER = -2, // This method should never be inlined, regardless of context + INLINE_FAIL = -1, // Inlining not OK for this case only + INLINE_NEVER = -2, // This method should never be inlined, regardless of context }; enum CorInfoInlineTypeCheck @@ -2042,11 +2034,6 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE calleeHnd /* IN */ ) = 0; - // Report that an inlining related process has begun. This will always be paired with - // a call to reportInliningDecision unless the jit fails. - virtual void beginInlining (CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) = 0; - // Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all // inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the // JIT. diff --git a/src/coreclr/inc/corjit.h b/src/coreclr/inc/corjit.h index 380db270e1cbf..54aaded8f9018 100644 --- a/src/coreclr/inc/corjit.h +++ b/src/coreclr/inc/corjit.h @@ -330,8 +330,7 @@ class ICorJitInfo : public ICorDynamicInfo // Data structure for a single class probe using 32-bit count. // - // CLASS_FLAG, INTERFACE_FLAG and DELEGATE_FLAG are placed into the Other field in the schema. - // If CLASS_FLAG is set the handle table consists of type handles, and otherwise method handles. + // CLASS_FLAG and INTERFACE_FLAG are placed into the Other field in the schema // // Count is the number of times a call was made at that call site. // @@ -339,8 +338,8 @@ class ICorJitInfo : public ICorDynamicInfo // // SAMPLE_INTERVAL must be >= SIZE. SAMPLE_INTERVAL / SIZE // gives the average number of calls between table updates. - // - struct HandleHistogram32 + // + struct ClassProfile32 { enum { @@ -348,18 +347,17 @@ class ICorJitInfo : public ICorDynamicInfo SAMPLE_INTERVAL = 32, CLASS_FLAG = 0x80000000, INTERFACE_FLAG = 0x40000000, - DELEGATE_FLAG = 0x20000000, - OFFSET_MASK = 0x0FFFFFFF + OFFSET_MASK = 0x3FFFFFFF }; uint32_t Count; - void* HandleTable[SIZE]; + CORINFO_CLASS_HANDLE ClassTable[SIZE]; }; - struct HandleHistogram64 + struct ClassProfile64 { uint64_t Count; - void* HandleTable[HandleHistogram32::SIZE]; + CORINFO_CLASS_HANDLE ClassTable[ClassProfile32::SIZE]; }; enum class PgoInstrumentationKind @@ -389,7 +387,7 @@ class ICorJitInfo : public ICorDynamicInfo Done = None, // All instrumentation schemas must end with a record which is "Done" BasicBlockIntCount = (DescriptorMin * 1) | FourByte, // basic block counter using unsigned 4 byte int BasicBlockLongCount = (DescriptorMin * 1) | EightByte, // basic block counter using unsigned 8 byte int - HandleHistogramIntCount = (DescriptorMin * 2) | FourByte | AlignPointer, // 4 byte counter that is part of a type histogram. Aligned to match HandleHistogram32's alignment. + HandleHistogramIntCount = (DescriptorMin * 2) | FourByte | AlignPointer, // 4 byte counter that is part of a type histogram. Aligned to match ClassProfile32's alignment. HandleHistogramLongCount = (DescriptorMin * 2) | EightByte, // 8 byte counter that is part of a type histogram HandleHistogramTypes = (DescriptorMin * 3) | TypeHandle, // Histogram of type handles HandleHistogramMethods = (DescriptorMin * 3) | MethodHandle, // Histogram of method handles @@ -398,7 +396,6 @@ class ICorJitInfo : public ICorDynamicInfo EdgeIntCount = (DescriptorMin * 6) | FourByte, // edge counter using unsigned 4 byte int EdgeLongCount = (DescriptorMin * 6) | EightByte, // edge counter using unsigned 8 byte int GetLikelyClass = (DescriptorMin * 7) | TypeHandle, // Compressed get likely class data - GetLikelyMethod = (DescriptorMin * 7) | MethodHandle, // Compressed get likely method data }; struct PgoInstrumentationSchema @@ -421,7 +418,7 @@ class ICorJitInfo : public ICorDynamicInfo Sampling= 6, // PGO data derived from sampling }; -#define DEFAULT_UNKNOWN_HANDLE 1 +#define DEFAULT_UNKNOWN_TYPEHANDLE 1 #define UNKNOWN_HANDLE_MIN 1 #define UNKNOWN_HANDLE_MAX 33 diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index 9a78c69a3423e..d7d8378cd1f84 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -565,8 +565,6 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_LOONGARCH64) #define DAC_CS_NATIVE_DATA_SIZE 96 -#elif defined(TARGET_LINUX) && defined(TARGET_POWERPC64) -#define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_ARM) diff --git a/src/coreclr/inc/defaultallocator.h b/src/coreclr/inc/defaultallocator.h new file mode 100644 index 0000000000000..111fb5e7f94c0 --- /dev/null +++ b/src/coreclr/inc/defaultallocator.h @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef _DEFAULTALLOCATOR_H_ +#define _DEFAULTALLOCATOR_H_ + +// The "DefaultAllocator" class may be used by classes that wish to +// provide the flexibility of using an "IAllocator" may avoid writing +// conditionals at allocation sites about whether a non-default +// "IAllocator" has been provided: if none is, they can simply set the +// allocator to DefaultAllocator::Singleton(). +class DefaultAllocator: public IAllocator +{ + static DefaultAllocator s_singleton; + +public: + void* Alloc(size_t sz) + { + return ::operator new(sz); + } + + void* ArrayAlloc(size_t elemSize, size_t numElems) + { + ClrSafeInt safeElemSize(elemSize); + ClrSafeInt safeNumElems(numElems); + ClrSafeInt sz = safeElemSize * safeNumElems; + if (sz.IsOverflow()) + { + return NULL; + } + else + { + return ::operator new(sz.Value()); + } + } + + virtual void Free(void * p) + { + ::operator delete(p); + } + + static DefaultAllocator* Singleton() + { + return &s_singleton; + } +}; + +#endif // _DEFAULTALLOCATOR_H_ diff --git a/src/coreclr/inc/iallocator.h b/src/coreclr/inc/iallocator.h index f8e0978c6f10f..a5b467a9905b8 100644 --- a/src/coreclr/inc/iallocator.h +++ b/src/coreclr/inc/iallocator.h @@ -29,4 +29,48 @@ class IAllocator virtual void Free(void* p) = 0; }; +// This class wraps an allocator that does not allow zero-length allocations, +// producing one that does (every zero-length allocation produces a pointer to the same +// statically-allocated memory, and freeing that pointer is a no-op). +class AllowZeroAllocator: public IAllocator +{ + int m_zeroLenAllocTarg; + IAllocator* m_alloc; + +public: + AllowZeroAllocator(IAllocator* alloc) : m_alloc(alloc) {} + + void* Alloc(size_t sz) + { + if (sz == 0) + { + return (void*)(&m_zeroLenAllocTarg); + } + else + { + return m_alloc->Alloc(sz); + } + } + + void* ArrayAlloc(size_t elemSize, size_t numElems) + { + if (elemSize == 0 || numElems == 0) + { + return (void*)(&m_zeroLenAllocTarg); + } + else + { + return m_alloc->ArrayAlloc(elemSize, numElems); + } + } + + virtual void Free(void * p) + { + if (p != (void*)(&m_zeroLenAllocTarg)) + { + m_alloc->Free(p); + } + } +}; + #endif // _IALLOCATOR_DEFINED_ diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 4864b03309694..87f3054e6269e 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -44,10 +44,6 @@ CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd) override; -void beginInlining( - CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) override; - void reportInliningDecision( CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 9a6cbc053e1ce..e03d9d9190c60 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* f2faa5fc-a1ec-4244-aebb-5597bfd7153a */ - 0xf2faa5fc, - 0xa1ec, - 0x4244, - {0xae, 0xbb, 0x55, 0x97, 0xbf, 0xd7, 0x15, 0x3a} +constexpr GUID JITEEVersionIdentifier = { /* 5868685e-b877-4ef5-83f0-73d601e50013 */ + 0x5868685e, + 0xb877, + 0x4ef5, + {0x83, 0xf0, 0x73, 0xd6, 0x01, 0xe5, 0x00, 0x13} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index a500c298978b6..e40eb4105ee3c 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -328,14 +328,9 @@ #endif JITHELPER(CORINFO_HELP_PATCHPOINT, JIT_Patchpoint, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, JIT_PartialCompilationPatchpoint, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_CLASSPROFILE32, JIT_ClassProfile32, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CLASSPROFILE64, JIT_ClassProfile64, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_DELEGATEPROFILE32, JIT_DelegateProfile32, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_DELEGATEPROFILE64, JIT_DelegateProfile64, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_VTABLEPROFILE32, JIT_VTableProfile32, CORINFO_HELP_SIG_4_STACK) - JITHELPER(CORINFO_HELP_VTABLEPROFILE64, JIT_VTableProfile64, CORINFO_HELP_SIG_4_STACK) + JITHELPER(CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, JIT_PartialCompilationPatchpoint, CORINFO_HELP_SIG_REG_ONLY) #if defined(TARGET_AMD64) || defined(TARGET_ARM64) JITHELPER(CORINFO_HELP_VALIDATE_INDIRECT_CALL, JIT_ValidateIndirectCall, CORINFO_HELP_SIG_REG_ONLY) diff --git a/src/coreclr/inc/llvm/ELF.h b/src/coreclr/inc/llvm/ELF.h index b38ecf9eba73a..9e89b48b514a3 100644 --- a/src/coreclr/inc/llvm/ELF.h +++ b/src/coreclr/inc/llvm/ELF.h @@ -829,7 +829,7 @@ struct Elf32_Sym { void setBinding(unsigned char b) { setBindingAndType(b, getType()); } void setType(unsigned char t) { setBindingAndType(getBinding(), t); } void setBindingAndType(unsigned char b, unsigned char t) { - st_info = (unsigned char)((b << 4) + (t & 0x0f)); + st_info = (b << 4) + (t & 0x0f); } }; @@ -849,7 +849,7 @@ struct Elf64_Sym { void setBinding(unsigned char b) { setBindingAndType(b, getType()); } void setType(unsigned char t) { setBindingAndType(getBinding(), t); } void setBindingAndType(unsigned char b, unsigned char t) { - st_info = (unsigned char)((b << 4) + (t & 0x0f)); + st_info = (b << 4) + (t & 0x0f); } }; diff --git a/src/coreclr/inc/pedecoder.h b/src/coreclr/inc/pedecoder.h index 2bb79e34b6b01..7cd145f452082 100644 --- a/src/coreclr/inc/pedecoder.h +++ b/src/coreclr/inc/pedecoder.h @@ -83,8 +83,6 @@ inline CHECK CheckOverflow(RVA value1, COUNT_T value2) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM64 #elif defined(TARGET_LOONGARCH64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_LOONGARCH64 -#elif defined(TARGET_POWERPC64) -#define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_POWERPC #elif defined(TARGET_S390X) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_UNKNOWN #else diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 20db29298cfba..76354362d57d8 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -16,7 +16,7 @@ // Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs #define READYTORUN_MAJOR_VERSION 0x0006 -#define READYTORUN_MINOR_VERSION 0x0002 +#define READYTORUN_MINOR_VERSION 0x0001 #define MINIMUM_READYTORUN_MAJOR_VERSION 0x006 diff --git a/src/coreclr/inc/regex_base.h b/src/coreclr/inc/regex_base.h new file mode 100644 index 0000000000000..fd6103f5da4b3 --- /dev/null +++ b/src/coreclr/inc/regex_base.h @@ -0,0 +1,972 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// Provides basic interpreted regular expression matching. This is meant as a debugging tool, +// and if regular expressions become necessary in a non-debug scenario great care should be +// used to ensure that performance is not impaired, and a more thorough review of this could +// would also be a good thing. This file does not include any concrete instantiations but +// instead provides the basic building blocks. Some concrete instantiations can be found in +// regex_util.h. +// +// NOTE: See code:clr::regex::RegExBase (below) for description of supported regex language. +// +// NOTE: we had to forego standard options such as tr1::regex +// (http://en.wikipedia.org/wiki/Technical_Report_1#Regular_Expressions) and Microsoft's +// internal GRETA regular expressions (http://toolbox/sites/987/default.aspx) because they +// both rely heavily on the STL, which can not currently be used within the CLR. +// +// NOTE: If this becomes non-debug-only, then read the comment on WCHARItemTraits for what +// what needs fixing. +// + +// + +#ifndef _REGEX_BASE_H_ +#define _REGEX_BASE_H_ + +// Forward declare namespace so that it is not debug-only (even if currently there is nothing +// but debug-only code in the namespace). This enables a "using namespace clr;" line in a +// header file without having to worry about whether or not it's in a debug-only block. +namespace clr {} + +#ifdef _DEBUG + +#include "utilcode.h" // for string hash functions +#include "sstring.h" + +namespace clr { +namespace regex { + +// Implementation details. Code contained in any "imp" namespace should never be directly used +// by clients of RegEx. +namespace imp { + + //=================================================================================================== + // Helper for clr::regex::RegExBase. See class definition for clr::regex::RegExBase below for more + // information. + + template + class RegExBaseHelper : protected ITEM_TRAITS + { + public: + typedef typename ITEM_TRAITS::RegexIterator RegexIterator; + typedef typename ITEM_TRAITS::InputIterator InputIterator; + + typedef typename ITEM_TRAITS::MatchFlags MatchFlags; + static const MatchFlags DefaultMatchFlags = ITEM_TRAITS::DefaultMatchFlags; + + // Arguments: + // regex : marks the start of the regular expression string. + // regexEnd : marks the end of the regular expression string. + // input : marks the start of the input string against which regex will be matched. + // inputEnd : marks the end of the input string. + // groups : recipient of regular expression groups. + // + // Returns true if the regular expression was successfully matched against the input string; + // otherwise false. + + RegExBaseHelper(const RegexIterator& regex, + const RegexIterator& regexEnd, + const InputIterator& input, + const InputIterator& inputEnd, + GROUP_CONTAINER& groups, + const MatchFlags flags = DefaultMatchFlags); + + // The main entrypoint to RegExBaseHelper, Match will attempt to match the regular expression + // defined by [regex,regexEnd) against the input defined by [input,inputEnd). + bool Match() + { WRAPPER_NO_CONTRACT; return DoMatch(m_regex, m_input); } + + protected: + typedef typename ITEM_TRAITS::Item Item; + typedef typename ITEM_TRAITS::ItemType ItemType; + + // Try to match regex at any point within input, starting with the first character and moving + // along one at a time until a match is found or the end of the input is encountered, whichever + // comes first. + bool DoMatch( + const RegexIterator& regex, + InputIterator input); + + // Try to match regex starting exactly at input. + bool DoMatchHere( + const RegexIterator& regex, + const InputIterator& input); + + // The function returns true if a match is found consisting of zero or more items c followed by a + // successful match of regex on the remaining input; otherwise false is returned. This is a + // conservative match, so it starts with trying to match zero items followed by regex, + // and will then try to match one item followed by regex. + bool DoMatchStar( + const Item& c, + const RegexIterator& regex, + InputIterator input); + + // The function returns true if a match is found consisting of zero or more items c followed by a + // successful match of regex on the remaining input; otherwise false is returned. This is a + // greedy match, so it starts with trying to match as many items as it can followed by regex, + // and on failure will try again with one less items matched. + bool DoMatchStarEagerly( + const Item& c, + const RegexIterator& regex, + InputIterator input); + + // Convenience method. + Item GetItem( + const RegexIterator ®ex) + { WRAPPER_NO_CONTRACT; return ITEM_TRAITS::GetItem(regex, m_regexEnd, m_flags); } + + // Convenience method. + bool MatchItem( + const Item& c, + const InputIterator& input) + { WRAPPER_NO_CONTRACT; return ITEM_TRAITS::MatchItem(c, input, m_inputEnd, m_flags); } + + // Declared as protected to prevent direct instantiation. + RegExBaseHelper() + {} + + RegexIterator m_regex; + RegexIterator m_regexEnd; + InputIterator m_input; + InputIterator m_inputEnd; + GROUP_CONTAINER& m_groups; + MatchFlags m_flags; + }; + + //--------------------------------------------------------------------------------------------------- + // This method simply stores the end iterators for the regular expression and the input strings, as + // well as the group collection object and flags, and forwards the call to DoMatch. + + template + RegExBaseHelper::RegExBaseHelper( + const RegexIterator& regex, + const RegexIterator& regexEnd, + const InputIterator& input, + const InputIterator& inputEnd, + GROUP_CONTAINER& groups, + const MatchFlags flags) + : m_regex(regex), + m_regexEnd(regexEnd), + m_input(input), + m_inputEnd(inputEnd), + m_groups(groups), + m_flags(flags) + { WRAPPER_NO_CONTRACT; } + + //--------------------------------------------------------------------------------------------------- + // This method checks if the regular expression starts with a caret, indicating that any match must + // be anchored at the start of the input string. If such a caret exists, one match attempt is made + // on the input starting with the first character and the result is returned. If the regex does not + // start with a caret, the method attempts to match against the input string, starting at the first + // character and moving one character over for each successive attempt, until a match is found or + // the end of the input is encountered, whichever comes first. + + template + inline bool + RegExBaseHelper::DoMatch( + const RegexIterator& regex, + InputIterator input) + { + WRAPPER_NO_CONTRACT; + + if (GetItem(regex).GetType() == ITEM_TRAITS::CARET) + { // Match must occur from the beginning of the line + m_groups.OpenGroup(input, m_inputEnd); + bool res = DoMatchHere(regex+1, input); + if (!res) + m_groups.CancelGroup(); + return res; + } + else + { // Match can happen anywhere in the string + do + { // Attempt to match against each substring [x,inputEnd) for x = 0...inputEnd + + // Begin the group that contains the entire match. + m_groups.OpenGroup(input, m_inputEnd); + + if (DoMatchHere(regex, input)) + { // Success. Note that the entire match group is closed elsewhere on a + // successful match. + return true; + } + + // On failure, cancel the group so that it can be reopened on the new substring + m_groups.CancelGroup(); + } while (input++ != m_inputEnd); + } + + // No successful match found. + return false; + } + + //------------------------------------------------------------------------------------------------------- + // This is the main loop, which handles grouping constructs, repetition directives (*, *?, +, +?), and + // EOL matches ($), delegating all character matching to ITEM_TRAITS::MatchItem + // The general algorithm is: + // 1. Get the next item. + // 2. If the item is a DOLLAR type, check to see if we're at the end of the retular expression and + // the input string, and if so return success. + // 3. If the item is a grouping construct, open or close the appropriate group and continue matching. + // On failure, roll back the grouping change so that subsequent attemts will have correct state. + // 4. Check to see if the item following the current is a repetition directive, and if so take the + // appropriate action. + // 5. Otherwise defer to ITEM_TRAITS::MatchItem and if successful continue to match the remaining + // regular expression and input string; otherwise return failure. + + template + inline bool + RegExBaseHelper::DoMatchHere( + const RegexIterator& regex, + const InputIterator& input) + { + WRAPPER_NO_CONTRACT; + + if (regex == m_regexEnd) + { // Reached the end of the regular expression without ever returning false, + // implying a successful match. Close the overall match group and return. + m_groups.CloseGroup(input); + return true; + } + + Item c0 = GetItem(regex); + if (c0.GetType() == ITEM_TRAITS::DOLLAR && (c0.GetNext() == m_regexEnd)) + { // Matches EOL if a '$' is encountered at the end of the input. + m_groups.CloseGroup(input); + // Success only if we're actually at the end of the input string. + return input == m_inputEnd; + } + if (c0.GetType() == ITEM_TRAITS::PAREN_OPEN) + { // Encountered an open parenthesis ('('); open a new grouping. + m_groups.OpenGroup(input, m_inputEnd); + bool res = DoMatchHere(c0.GetNext(), input); + if (!res) + { // If a match fails, there could be further attempts (such as if + // there is an active repetition matching frame beneath us), so + // need to cancel the group we just opened so that the grouping + // structure remains consistent. + m_groups.CancelGroup(); + } + return res; + } + if (c0.GetType() == ITEM_TRAITS::PAREN_CLOSE) + { // Close the most recent open grouping. + COUNT_T i = m_groups.CloseGroup(input); + bool res = DoMatchHere(c0.GetNext(), input); + if (!res) + { // For the same reasons as the need to cancel an opened group + // explained above, we need to reopen the closed group if a + // match fails. + m_groups.ReopenGroup(i, m_inputEnd); + } + return res; + } + + if (c0.GetNext() != m_regexEnd) + { // If there is another item in the regex string following the current one, get + // it to see if it is a repetition matching directive. + Item c1 = GetItem(c0.GetNext()); + if (c1.GetType() == ITEM_TRAITS::STAR) + { // '*' matching directive encountered + if (c1.GetNext() != m_regexEnd) + { + Item c2 = GetItem(c1.GetNext()); + if (c2.GetType() == ITEM_TRAITS::QUESTION_MARK) + { // conservative matching semantics requested + return DoMatchStar(c0, c2.GetNext(), input); + } + } + // Eager matching + return DoMatchStarEagerly(c0, c1.GetNext(), input); + } + if (c1.GetType() == ITEM_TRAITS::PLUS) + { // '+' matching directive encountered. + if (c1.GetNext() != m_regexEnd) + { + Item c2 = GetItem(c1.GetNext()); + if (c2.GetType() == ITEM_TRAITS::QUESTION_MARK) + { // conservative matching semantics requested + return MatchItem(c0, input) && DoMatchStar(c0, c2.GetNext(), input+1); + } + } + // Eager matching + return MatchItem(c0, input) && DoMatchStarEagerly(c0, c1.GetNext(), input+1); + } + if (c1.GetType() == ITEM_TRAITS::QUESTION_MARK) + { // '?' matching directive encountered + return (MatchItem(c0, input) && DoMatchHere(c1.GetNext(), input+1)) || DoMatchHere(c1.GetNext(), input); + } + } + + // No special matching semantics encountered, delegate the matching to ITEM_TRAITS::MatchItem + return MatchItem(c0, input) && DoMatchHere(c0.GetNext(), input+1); + } + + //------------------------------------------------------------------------------------------------------- + // Conservative '*' repetition matching. This attempts to match zero items c followed by a match of + // regex. If this fails, attempt to match one item c followed by a match of regex. Repeat until item c + // does not match or a successful match is found. + + template + inline bool + RegExBaseHelper::DoMatchStar( + const Item& c, + const RegexIterator& regex, + InputIterator input) + { + WRAPPER_NO_CONTRACT; + CONSISTENCY_CHECK(input != m_inputEnd); + + do { + if (DoMatchHere(regex, input)) + { // A successful match is found! + return true; + } + // No successful match, so try to match one more item and then attempt to match regex on the + // remaining input. + } while (input != m_inputEnd && MatchItem(c, input++)); + return false; + } + + //------------------------------------------------------------------------------------------------------- + // Similar to DoMatchStar above, except this algorithm matches as many items c as possible first followed + // by regex on the remaining input, and on failure tries again with a match against one less item c + // followed by regex on the remaining input, and repeats until there are no items c remaining to match + // and the zero item match followed by a match of regex on the entire remaining input fails. If any of + // the match attempts succeed, return success. + + template + inline bool + RegExBaseHelper::DoMatchStarEagerly( + const Item& c, + const RegexIterator& regex, + InputIterator input) + { + WRAPPER_NO_CONTRACT; + + // Make sure we keep a hold of how far back we can unwind. + InputIterator inputOrig = input; + + // First, determine the maximum number of matches against item c. + while (input != m_inputEnd && MatchItem(c, input)) + { + ++input; + } + + do + { // Work backwards from the maximum number of matches of item c until a match is found + // or until we have backed right up to the starting value of input (saved in inputOrig), + // at which time we admit failure. + if (DoMatchHere(regex, input)) + return true; + } while (inputOrig != input--); + return false; + } + +} // namespace imp + +//======================================================================================================= +// Represents a matched group using iterators to denote the string contained by [Begin(),End()). + +template +class Group +{ +public: + typedef INPUT_ITERATOR InputIterator; + + // + // Functions for accessing group properties + // + + // Returns the iterator indicating the start of the group + const InputIterator& Begin() const + { LIMITED_METHOD_CONTRACT; return m_begin; } + + // Returns the iterator indicating the first non-member of the group + const InputIterator& End() const + { LIMITED_METHOD_CONTRACT; return m_end; } + + // It is possible that m_end - m_begin could be greater than the maximum of COUNT_T. m_end and + // m_begin are the end and start of a string, so is entirely unlikely to overflow a COUNT_T. + // Conbined with the fact that this is debug-only code, opting not to replace all COUNT_T + // uses with SIZE_T. + COUNT_T Length() const + { WRAPPER_NO_CONTRACT; return static_cast(m_end - m_begin); } + + // + // Functions used by RegExBaseHelper to create grouping constructs. + // + + Group() + : m_isClosed(false), m_begin(), m_end() + { WRAPPER_NO_CONTRACT; } + + Group(const InputIterator& start, const InputIterator& end, bool isClosed = false) + : m_isClosed(isClosed), m_begin(start), m_end(end) + { WRAPPER_NO_CONTRACT; } + + void SetBegin(const InputIterator& start) + { WRAPPER_NO_CONTRACT; m_begin = start; } + + void SetEnd(const InputIterator& end) + { WRAPPER_NO_CONTRACT; m_end = end; } + + bool IsClosed() const + { LIMITED_METHOD_CONTRACT; return m_isClosed; } + + void SetIsClosed(bool isClosed) + { WRAPPER_NO_CONTRACT; m_isClosed = isClosed; } + +protected: + bool m_isClosed; + InputIterator m_begin; + InputIterator m_end; +}; + +//======================================================================================================= +// Represents a generic container of groups, defaulting to using Group as its element +// type. This container satisfies the method requrements of RegExBase. When a match is successful, the +// match groups may be accessed using the index operator or the iterators definin the matched groups +// [Begin(), End()). + +template > +class GroupContainer +{ +public: + typedef typename SArray::Iterator Iterator; + + // + // Functions for enumerating groups + // + + GROUP_TYPE & operator[](COUNT_T idx) + { + WRAPPER_NO_CONTRACT; + CONSISTENCY_CHECK(((COUNT_T)(COUNT_T)idx) == idx); + return m_array[idx]; + } + + // Returns an iterator to the first matched group (which is always the string for the + // entire successfully matched string. Specific groups start at Begin()+1 and continue + // to End()-1. + Iterator Begin() + { WRAPPER_NO_CONTRACT; return m_array.Begin(); } + + // Returns the first invalid iterator value. + Iterator End() + { WRAPPER_NO_CONTRACT; return m_array.End(); } + + // + COUNT_T Count() const + { WRAPPER_NO_CONTRACT; return m_array.GetCount(); } + + // + // Functions used by RegExBaseHelper to create grouping constructs. + // + + // Note: OpenGroup takes an end iterator so that the group will have a valid (if possibly + // incorrect) endpoint in the case that the regular expression has unbalanced grouping + // parentheses. + void OpenGroup(const INPUT_ITERATOR& start, const INPUT_ITERATOR& end) + { WRAPPER_NO_CONTRACT; m_array.Append(GROUP_TYPE(start, end, false)); } + + COUNT_T CloseGroup(const INPUT_ITERATOR& end); + + void ReopenGroup(COUNT_T i, const INPUT_ITERATOR& end); + + void CancelGroup() + { WRAPPER_NO_CONTRACT; m_array.Delete(m_array.End() - 1); } + +private: + SArray m_array; +}; + +//------------------------------------------------------------------------------------------------------- +// Works backwards from the most recently created group looking for an open group to close. Returns +// the index of the group that was closed, which is used in the event that a group needs to be +// reopened. + +template +COUNT_T +GroupContainer::CloseGroup( + const INPUT_ITERATOR& end) +{ + WRAPPER_NO_CONTRACT; + + for (COUNT_T i = (COUNT_T)Count(); i > 0; --i) + { + if (!m_array[i-1].IsClosed()) + { + m_array[i-1].SetEnd(end); + m_array[i-1].SetIsClosed(true); + return i-1; + } + } + + _ASSERTE(!"Unmatched grouping constructs!"); + return 0; +} + +//------------------------------------------------------------------------------------------------------- +// Reopen a group at the given index, using 'end' to overwrite the current end. + +template +void +GroupContainer::ReopenGroup( + COUNT_T i, + const INPUT_ITERATOR& end) +{ + WRAPPER_NO_CONTRACT; + CONSISTENCY_CHECK(i > 0 && i < Count()); + + if (i > 0 && i < Count()) + { + m_array[i].SetEnd(end); + m_array[i].SetIsClosed(false); + } +} + +//======================================================================================================= +// Empty group container that satisfies the method requirements of RegExBase but has empty bodies. This +// allows for non-allocating matches when grouping is not required. + +template +class NullGroupContainer +{ +public: + void OpenGroup(INPUT_ITERATOR, INPUT_ITERATOR) {} + COUNT_T CloseGroup(INPUT_ITERATOR) { return 0; } + void ReopenGroup(COUNT_T, INPUT_ITERATOR) {} + void CancelGroup() {} +}; + +//======================================================================================================= +// This mini-implementation of regular expression matching supports the +// following constructs: +// ^ matches the beginning of the input string +// $ matches the end of the input string +// * matches zero or more occurrences of the previous item eagerly +// *? matches zero or more occurrences of the previous item conservatively +// + matches 1 or more occurrences of the previous item eagerly +// +? matches 1 or more occurrences of the previous item conservatively +// ? matches 0 or 1 occurrences of the previous item +// ( starts a grouping +// ) ends a grouping +// +// IMPORTANT: These are just anchoring and grouping constructs. See the definition for ItemTraitsBase +// below for information on the default character classes that are supported. (The intent of +// this separation is to allow customization of the character classes where required.) + +// ITEM_TRAITS provides traits for individual tokens in a regular expression, as well as a mechanism for +// matching said individual components with the target string. RegexBase derives from ITEM_TRAITS in a +// protected fashion, and is responsible for providing the following: +// 1. "RegexIterator" typedef +// Used as an iterator into the regular expression, and used as arguments to indicate the start +// and the end of the regular expression string. +// 2. "InputIterator" typedef +// Used as an iterator into the input string, and used as arguments to indicate the start +// and the end of the input string. +// (NOTE: RegexIterator and InputIterator are often typedef'ed to be the same thing.) +// 3. "Item" typedef. +// This will be used with methods GetItem and MatchItem (see below). Item must +// define the following methods: +// ItemType GetType() : returns the type of the item. See below for explanation of ItemType +// const RegexIterator& GetNext() : iterator pointing to the start of the next item. +// 4. "MatchFlags" typedef, and "static const DefaultMatchFlags" value. +// Provided for calls to "Match" and "Matches", and passed on to calls "GetItem" and "MatchItem". +// 5. enum ItemType +// Defines the following minimum values: +// DOT +// CARET +// DOLLAR +// STAR +// QUESTION_MARK +// PLUS +// PAREN_OPEN +// PAREN_CLOSE +// ItemType may include more values, and may even choose to ignore the above enum types, all of +// which must be recognized by GetItem and MatchItem (see below). +// 6. static Item GetItem(const RegexIterator& regex, +// const RegexIterator& regexEnd, +// const MatchFlags& flags) +// This method takes a regular expression iterator and returns the next regular expression +// element (Item) pointed to by the iterator. +// 7. static bool MatchItem(const Item& c, +// const InputIterator& input, +// const InputIterator& inputEnd, +// const MatchFlags &flags) + +// GROUP_CONTAINER provides functionality for keeping track of regular expression groups. This is a generic +// argument to Match, and the type of the object must support the following methods: +// 1. void OpenGroup(const InputIterator& start, const InputIterator& end); +// Called when a PAREN_OPEN item is encountered. +// 2. COUNT_T CloseGroup(const InputIterator& end); +// Called when a PAREN_CLOSE item is encountered. Returns the index of the group that was closed. +// 3. void ReopenGroup(COUNT_T i, const InputIterator& end); +// Called when a match following a call to CloseGroup fails, essentially requesting a rollback +// of the call to CloseGroup. +// 4. void CancelGroup(); +// Called when a match following a call to OpenGroup fails, essentially requesting a rollback +// of the call to OpenGroup. + +template +class RegExBase : public ITEM_TRAITS +{ +public: + typedef typename ITEM_TRAITS::RegexIterator RegexIterator; + typedef typename ITEM_TRAITS::InputIterator InputIterator; + + // This is a convenience typedef that allows a caller to easily declare a grouping container + // to be passed to a call to Match. An example would be (see regex_util.h for a definition of + // SStringRegEx): + // + // SString input(SL"Simmons"); + // SStringRegEx::GroupingContainer container; + // if (SStringRegEx::Match(SL"(Sim+on)", input, container)) { + // printf("%S", container[1].GetSString(input).GetUnicode()); + // } + // + typedef GroupContainer > GroupingContainer; + + // Pulls down the typedef for MatchFlags and initialized a static representing the default flags. + typedef typename ITEM_TRAITS::MatchFlags MatchFlags; + static const MatchFlags DefaultMatchFlags = ITEM_TRAITS::DefaultMatchFlags; + + template + static bool Match(RegexIterator regex, + RegexIterator regexEnd, + InputIterator input, + InputIterator inputEnd, + GROUP_CONTAINER& groups, + MatchFlags flags = DefaultMatchFlags) + { + imp::RegExBaseHelper + re(regex, regexEnd, input, inputEnd, groups, flags); + return re.Match(); + } + + static bool Matches(RegexIterator regex, + RegexIterator regexEnd, + InputIterator input, + InputIterator inputEnd, + MatchFlags flags = DefaultMatchFlags) + { + NullGroupContainer ngc; + return Match(regex, regexEnd, input, inputEnd, ngc, flags); + } +}; + +//======================================================================================================= +// In addition to requirements specified on RegExBase, StandardItemTraits provides the following +// additinal regular expression item types. +// c matches any literal character c +// . matches any single character +// \d any literal digit character +// \w any alpha character +// \s any whitespace character +// +// Child types of ItemTraitsBase must implement GetItem and MatchItem (see below for full +// signature requirements). Current child type implementations permit a backslash ('\') to escape +// special characters ('.', '$', '*', etc.) and allow them to be interpreted as literal characters. +// +// This type describes a particular behaviour, but must be subtyped for the particular target character +// needed, and GetItem and MatchItem must be implemented. +// + +template +class ItemTraitsBase +{ +public: + typedef ITERATOR_TYPE RegexIterator; + typedef ITERATOR_TYPE InputIterator; + + enum MatchFlags + { + MF_NONE = 0x00, + MF_CASE_INSENSITIVE = 0x01 // Match character literals as case insensitive. + }; + + static const MatchFlags DefaultMatchFlags = MF_NONE; + +protected: + ItemTraitsBase() + {} + + enum ItemType + { + // REQUIRED, as described in RegExBase + CARET, + DOLLAR, + STAR, + QUESTION_MARK, + PLUS, + PAREN_OPEN, + PAREN_CLOSE, + // ADDITIONAL + DOT, // any literal character + DIGIT, // any digit + ALPHA, // any alpha character, upper or lower case + WHITESPACE, // any whitespace character + NON_WHITESPACE, // any non-whitespace character + CHARACTER, // a specific literal character + }; + + class Item + { + public: + Item(ItemType type, CHAR_TYPE val, const RegexIterator& next) + : m_type(type), m_val(val), m_next(next) + { WRAPPER_NO_CONTRACT; } + + Item(ItemType type, const RegexIterator& next) + : m_type(type), m_val(0), m_next(next) + { WRAPPER_NO_CONTRACT; } + + ItemType GetType() const + { LIMITED_METHOD_CONTRACT; return m_type; } + + const RegexIterator& GetNext() const + { LIMITED_METHOD_CONTRACT; return m_next; } + + CHAR_TYPE GetValue() const + { LIMITED_METHOD_CONTRACT; return m_val; } + + protected: + ItemType m_type; + CHAR_TYPE m_val; + RegexIterator m_next; + }; + + // All deriving types must add the following methods: + // static Item GetItem(const RegexIterator& regex, const RegexIterator& regexEnd); + // static bool MatchItem(const Item& c, const InputIterator& input, const InputIterator& inputEnd); +}; + +//======================================================================================================= +// Implements ItemTraitsBase, provides matching for UNICODE characters. +// +// !!!IMPORTANT!!! +// This is not a complete unicode implementation - only the equivalent of ASCII alpha characters are +// consider to be part of the alpha set, and this is also the only set on which case insensitive +// operations will correctly work. If RegEx is moved out of DEBUG ONLY, then this will have to be fixed +// to properly address these issues. +// !!!IMPORTANT!!! + +template +class WCHARItemTraits : public ItemTraitsBase +{ +public: + typedef ItemTraitsBase PARENT_TYPE; + typedef typename PARENT_TYPE::RegexIterator RegexIterator; + typedef typename PARENT_TYPE::InputIterator InputIterator; + typedef typename PARENT_TYPE::Item Item; + typedef typename PARENT_TYPE::MatchFlags MatchFlags; + + static Item GetItem(const RegexIterator& regex, const RegexIterator& regexEnd, MatchFlags flags); + static bool MatchItem(const Item& c, const InputIterator& input, const InputIterator& inputEnd, MatchFlags flags); + +protected: + WCHARItemTraits() + {} + +private: + static inline bool IS_UPPER_A_TO_Z(WCHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= W('A')) && ((x) <= W('Z'))); } + + static inline bool IS_LOWER_A_TO_Z(WCHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= W('a')) && ((x) <= W('z'))); } + + static inline WCHAR UPCASE(WCHAR x) + { WRAPPER_NO_CONTRACT; return (IS_LOWER_A_TO_Z(x) ? ((x) - W('a') + W('A')) : (x)); } + + static inline WCHAR DOWNCASE(WCHAR x) + { WRAPPER_NO_CONTRACT; return (IS_UPPER_A_TO_Z(x) ? ((x) - W('A') + W('a')) : (x)); } + + static bool MatchCharacter(WCHAR c1, WCHAR c2, MatchFlags flags) + { WRAPPER_NO_CONTRACT; return (flags & PARENT_TYPE::MF_CASE_INSENSITIVE) ? (DOWNCASE(c1) == DOWNCASE(c2)) : (c1 == c2); } +}; + +//------------------------------------------------------------------------------------------------------- +// Reads the next item from regex, recognizing special characters outlined in ItemTraitsBase. + +template +typename WCHARItemTraits::Item +WCHARItemTraits::GetItem( + const RegexIterator& regex, + const RegexIterator& regexEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (*regex == W('\\')) + { + const RegexIterator regexNext = regex+1; + if (regexNext == regexEnd) + return Item(PARENT_TYPE::CHARACTER, W('\\'), regexNext); + if (*regexNext == W('d')) + return Item(PARENT_TYPE::DIGIT, regexNext+1); + if (*regexNext == W('w')) + return Item(PARENT_TYPE::ALPHA, regexNext+1); + if (*regexNext == W('s')) + return Item(PARENT_TYPE::WHITESPACE, regexNext+1); + if (*regexNext == W('S')) + return Item(PARENT_TYPE::NON_WHITESPACE, regexNext+1); + return Item(PARENT_TYPE::CHARACTER, *regexNext, regexNext+1); + } + else if (*regex == W('.')) + return Item(PARENT_TYPE::DOT, W('.'), regex+1); + else if (*regex == W('^')) + return Item(PARENT_TYPE::CARET, W('^'), regex+1); + else if (*regex == W('$')) + return Item(PARENT_TYPE::DOLLAR, W('$'), regex+1); + else if (*regex == W('*')) + return Item(PARENT_TYPE::STAR, W('*'), regex+1); + else if (*regex == W('?')) + return Item(PARENT_TYPE::QUESTION_MARK, W('?'), regex+1); + else if (*regex == W('+')) + return Item(PARENT_TYPE::PLUS, W('+'), regex+1); + else if (*regex == W('(')) + return Item(PARENT_TYPE::PAREN_OPEN, W('('), regex+1); + else if (*regex == W(')')) + return Item(PARENT_TYPE::PAREN_CLOSE, W(')'), regex+1); + else + return Item(PARENT_TYPE::CHARACTER, *regex, regex + 1); +} + +//------------------------------------------------------------------------------------------------------- +// Returns true if the next character point to by input matches the character class described by c. + +template +bool +WCHARItemTraits::MatchItem( + const Item& c, + const InputIterator& input, + const InputIterator& inputEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (c.GetType() == PARENT_TYPE::DIGIT) + return *input >= W('0') && *input <= W('9'); + else if (c.GetType() == PARENT_TYPE::ALPHA) + return (*input >= W('a') && *input <= W('z')) || (*input >= W('A') && *input <= W('Z')); + else if (c.GetType() == PARENT_TYPE::WHITESPACE) + return *input == W(' ') || *input == W('\t'); + else if (c.GetType() == PARENT_TYPE::NON_WHITESPACE) + return !(*input == W(' ') || *input == W('\t')); + else + return c.GetType() == PARENT_TYPE::DOT || MatchCharacter(c.GetValue(), *input, flags); +} + +//======================================================================================================= +// Implements ItemTraitsBase, provides matching for ASCII (*not* UTF8) characters. + +template +class CHARItemTraits : public ItemTraitsBase +{ +public: + typedef ItemTraitsBase PARENT_TYPE; + typedef typename PARENT_TYPE::RegexIterator RegexIterator; + typedef typename PARENT_TYPE::InputIterator InputIterator; + typedef typename PARENT_TYPE::Item Item; + typedef typename PARENT_TYPE::MatchFlags MatchFlags; + + static Item GetItem(const RegexIterator& regex, const RegexIterator& regexEnd, MatchFlags flags); + static bool MatchItem(const Item& c, const InputIterator& input, const InputIterator& inputEnd, MatchFlags flags); + +protected: + CHARItemTraits() + {} + +private: + static inline bool IS_UPPER_A_TO_Z(CHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= 'A') && ((x) <= 'Z')); } + + static inline bool IS_LOWER_A_TO_Z(CHAR x) + { WRAPPER_NO_CONTRACT; return (((x) >= 'a') && ((x) <= 'z')); } + + static inline CHAR UPCASE(CHAR x) + { WRAPPER_NO_CONTRACT; return (IS_LOWER_A_TO_Z(x) ? ((x) - 'a' + 'A') : (x)); } + + static inline CHAR DOWNCASE(CHAR x) + { WRAPPER_NO_CONTRACT; return (IS_UPPER_A_TO_Z(x) ? ((x) - 'A' + 'a') : (x)); } + + static bool MatchCharacter(CHAR c1, CHAR c2, MatchFlags flags) + { WRAPPER_NO_CONTRACT; return (flags & PARENT_TYPE::MF_CASE_INSENSITIVE) ? (DOWNCASE(c1) == DOWNCASE(c2)) : (c1 == c2); } +}; + +//------------------------------------------------------------------------------------------------------- +// Reads the next item from regex, recognizing special characters outlined in ItemTraitsBase. + +template +typename CHARItemTraits::Item +CHARItemTraits::GetItem( + const RegexIterator& regex, + const RegexIterator& regexEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (*regex == '\\') + { + const RegexIterator regexNext = regex+1; + if (regexNext == regexEnd) + return Item(PARENT_TYPE::CHARACTER, W('\\'), regexNext); + if (*regexNext == 'd') + return Item(PARENT_TYPE::DIGIT, regexNext+1); + if (*regexNext == 'w') + return Item(PARENT_TYPE::ALPHA, regexNext+1); + if (*regexNext == 's') + return Item(PARENT_TYPE::WHITESPACE, regexNext+1); + return Item(PARENT_TYPE::CHARACTER, *regexNext, regexNext+1); + } + else if (*regex == '.') + return Item(PARENT_TYPE::DOT, '.', regex+1); + else if (*regex == '^') + return Item(PARENT_TYPE::CARET, '^', regex+1); + else if (*regex == '$') + return Item(PARENT_TYPE::DOLLAR, '$', regex+1); + else if (*regex == '*') + return Item(PARENT_TYPE::STAR, '*', regex+1); + else if (*regex == '?') + return Item(PARENT_TYPE::QUESTION_MARK, '?', regex+1); + else if (*regex == '+') + return Item(PARENT_TYPE::PLUS, '+', regex+1); + else if (*regex == '(') + return Item(PARENT_TYPE::PAREN_OPEN, '(', regex+1); + else if (*regex == ')') + return Item(PARENT_TYPE::PAREN_CLOSE, ')', regex+1); + else + return Item(PARENT_TYPE::CHARACTER, *regex, regex + 1); +} + +//------------------------------------------------------------------------------------------------------- +// Returns true if the next character point to by input matches the character class described by c. + +template +bool +CHARItemTraits::MatchItem( + const Item& c, + const InputIterator& input, + const InputIterator& inputEnd, + MatchFlags flags) +{ + WRAPPER_NO_CONTRACT; + + if (c.GetType() == PARENT_TYPE::DIGIT) + return *input >= W('0') && *input <= W('9'); + else if (c.GetType() == PARENT_TYPE::ALPHA) + return (*input >= W('a') && *input <= W('z')) || (*input >= W('A') && *input <= W('Z')); + else if (c.GetType() == PARENT_TYPE::WHITESPACE) + return *input == W(' ') || *input == W('\t'); + else + return c.GetType() == PARENT_TYPE::DOT || MatchCharacter(c.GetValue(), *input, flags); +} + +} /* namespace regex */ +} /* namespace clr */ + +#endif // _DEBUG + +#endif // _REGEX_BASE_H_ diff --git a/src/coreclr/inc/regex_util.h b/src/coreclr/inc/regex_util.h new file mode 100644 index 0000000000000..d96c7423198b2 --- /dev/null +++ b/src/coreclr/inc/regex_util.h @@ -0,0 +1,208 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// See regex_base.h for more information. +// +// This header creates some concrete instantiations of RegExBase for commonly used scenarios. In +// particular, basic regular expression matching base on the regular expression language described in +// clr::regex::ItemTraitsBase (found in regex_base.h) is instantiated for use with SString, ASCII and +// UNICODE strings (clr::regex::SStringRegex, clr::regex::WSTRRegEx, and clr::regex::STRRegEx +// respectively). Each type definition includes an example of its use. +// + +// + +#ifndef _REGEX_UTIL_H_ +#define _REGEX_UTIL_H_ + +#ifndef MODE_ANY +#define MODE_ANY +#endif + +#include "regex_base.h" + +#ifdef _DEBUG + +namespace clr +{ +namespace regex +{ + +//======================================================================================================= +// Derives from Group to provide two additional convenience methods (GetSString variants). + +class SStringGroup : public Group +{ +public: + SStringGroup() + : Group() + { WRAPPER_NO_CONTRACT; } + + SStringGroup(const InputIterator& _start, const InputIterator& _end, bool _isClosed = false) + : Group(_start, _end, _isClosed) + { WRAPPER_NO_CONTRACT; } + + // Since SStrings constructed from ranges require the original source string, this is a required + // input argument. Returns the input substring that matches the corresponding grouping. + SString GetSString(const SString& src) + { WRAPPER_NO_CONTRACT; return SString(src, Begin(), End()); } + + // Since SStrings constructed from ranges require the original source string, this is a required + // input argument. This version takes a target SString as a buffer, and also returns this buffer + // as a reference. Returns the input substring that matches the corresponding grouping. + SString& GetSString(const SString& src, SString& tgt) + { WRAPPER_NO_CONTRACT; tgt.Set(src, Begin(), End()); return tgt; } +}; + +//======================================================================================================= +typedef WCHARItemTraits SStringItemTraits; + +//======================================================================================================= +// Regular expression matching with SStrings. +// +// Here is an example of how to use SStringRegEx with grouping enabled. +// +// using namespace clr::regex; +// SString input(SL"Simmons"); // usually this is derived from some variable source +// SStringRegEx::GroupingContainer container; +// if (SStringRegEx::Match(SL"(Sim+on)", input, container)) { +// printf("%S", container[1].GetSString(input).GetUnicode()); +// } +// +// This sample should result in "Simmon" being printed. + + +class SStringRegEx : public RegExBase +{ + typedef RegExBase PARENT_TYPE; + +public: + using PARENT_TYPE::Match; + using PARENT_TYPE::Matches; + + typedef PARENT_TYPE::InputIterator InputIterator; + + typedef GroupContainer GroupingContainer; + + static bool Match( + const SString& regex, + const SString& input, + GroupingContainer& groups, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Match(regex.Begin(), regex.End(), input.Begin(), input.End(), groups, flags); + } + + static bool Matches( + const SString& regex, + const SString& input, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Matches(regex.Begin(), regex.End(), input.Begin(), input.End(), flags); + } + +}; + +//======================================================================================================= +// Regular expression matching with UNICODE strings. +// +// Here is an example of how to use WSTRRegEx to match against a null-terminated string without grouping. +// +// using namespace clr::regex; +// LPCWSTR input = L"Simmons"; +// if (WSTRRegEx::Matches(L"Sim+on", input)) +// printf("Match succeeded"); +// else +// printf("Match failed"); +// +// This sample should result in "Match succeeded" being printed. + +class WSTRRegEx : public RegExBase > +{ + typedef RegExBase > PARENT_TYPE; + +public: + using PARENT_TYPE::Match; + using PARENT_TYPE::Matches; + + static bool Match( + LPCWSTR regex, + LPCWSTR input, + GroupingContainer& groups, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Match(regex, regex + wcslen(regex), input, input + wcslen(input), groups, flags); + } + + static bool Matches( + LPCWSTR regex, + LPCWSTR input, + MatchFlags flags = DefaultMatchFlags) + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } CONTRACTL_END; + + return Matches(regex, regex + wcslen(regex), input, input + wcslen(input), flags); + } +}; + +//======================================================================================================= +// Regular expression matching with ASCII strings. +// +// Here is an example of how to use STRRegEx to match against a substring based on begin and end range +// pointers, with grouping disabled and case insensitivity enabled. +// +// using namespace clr::regex; +// LPCSTR input = "123Simmons456"; +// if (STRRegEx::Matches("Sim+on", input+3, input+10, STRRegEx::MF_CASE_INSENSITIVE)) +// printf("Match succeeded"); +// else +// printf("Match failed"); +// +// This sample should result in "Match succeeded" being printed. + +class STRRegEx : public RegExBase > +{ + typedef RegExBase > PARENT_TYPE; + +public: + using PARENT_TYPE::Match; + using PARENT_TYPE::Matches; + + static bool Match( + LPCSTR regex, + LPCSTR input, + GroupingContainer& groups, + MatchFlags flags = DefaultMatchFlags) + { + WRAPPER_NO_CONTRACT; + return Match(regex, regex + strlen(regex), input, input + strlen(input), groups, flags); + } + + static bool Matches( + LPCSTR regex, + LPCSTR input, + MatchFlags flags = DefaultMatchFlags) + { + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } CONTRACTL_END; + + return Matches(regex, regex + strlen(regex), input, input + strlen(input), flags); + } +}; + +} // namespace regex +} // namespace clr + +#endif // _DEBUG + +#endif // _REGEX_UTIL_H_ diff --git a/src/coreclr/inc/sstring.h b/src/coreclr/inc/sstring.h index 3145d1b1e30de..5f5eeb1078e00 100644 --- a/src/coreclr/inc/sstring.h +++ b/src/coreclr/inc/sstring.h @@ -105,11 +105,16 @@ class EMPTY_BASES_DECL SString : private SBuffer protected: class Index; + class UIndex; friend class Index; + friend class UIndex; public: + // UIterator is character-level assignable. + class UIterator; + // CIterators/Iterator'string must be modified by SString APIs. class CIterator; class Iterator; @@ -168,7 +173,6 @@ class EMPTY_BASES_DECL SString : private SBuffer void SetASCII(const ASCII *string); void SetUTF8(const UTF8 *string); void SetANSI(const ANSI *string); - void SetAndConvertToUTF8(const WCHAR* string); // Set this string to a copy of the first count chars of the given string void Set(const WCHAR *string, COUNT_T count); @@ -321,6 +325,53 @@ class EMPTY_BASES_DECL SString : private SBuffer // CIterator and Iterator are cheap to create, but allow only read-only // access to the string. // + // UIterator forces a unicode conversion, but allows + // assignment to individual string characters. They are also a bit more + // efficient once created. + + // ------------------------------------------------------------------ + // UIterator: + // ------------------------------------------------------------------ + + protected: + + class EMPTY_BASES_DECL UIndex : public SBuffer::Index + { + friend class SString; + friend class Indexer; + + protected: + + UIndex(); + UIndex(SString *string, SCOUNT_T index); + WCHAR &GetAt(SCOUNT_T delta) const; + void Skip(SCOUNT_T delta); + SCOUNT_T Subtract(const UIndex &i) const; + CHECK DoCheck(SCOUNT_T delta) const; + + WCHAR *GetUnicode() const; + }; + + public: + + class EMPTY_BASES_DECL UIterator : public UIndex, public Indexer + { + friend class SString; + + public: + UIterator() + { + } + + UIterator(SString *string, int index) + : UIndex(string, index) + { + } + }; + + UIterator BeginUnicode(); + UIterator EndUnicode(); + // For CIterator & Iterator, we try our best to iterate the string without // modifying it. (Currently, we do require an ASCII or Unicode string // for simple WCHAR retrival, but you could imagine being more flexible @@ -493,15 +544,17 @@ class EMPTY_BASES_DECL SString : private SBuffer // SString *s = ...; // { // StackScratchBuffer buffer; - // const ANSI *ansi = s->GetANSI(buffer); - // CallFoo(ansi); + // const UTF8 *utf8 = s->GetUTF8(buffer); + // CallFoo(utf8); // } // // No more pointers to returned buffer allowed. + + const UTF8 *GetUTF8(AbstractScratchBuffer &scratch) const; + const UTF8 *GetUTF8(AbstractScratchBuffer &scratch, COUNT_T *pcbUtf8) const; const ANSI *GetANSI(AbstractScratchBuffer &scratch) const; - // You can always get a UTF8 string. This will force a conversion - // if necessary. - const UTF8 *GetUTF8() const; + // Used when the representation is known, throws if the representation doesn't match + const UTF8 *GetUTF8NoConvert() const; // Converts/copies into the given output string void ConvertToUnicode(SString &dest) const; @@ -726,7 +779,6 @@ class EMPTY_BASES_DECL SString : private SBuffer void ConvertASCIIToUnicode(SString &dest) const; void ConvertToUnicode() const; void ConvertToUnicode(const CIterator &i) const; - void ConvertToUTF8() const; const SString &GetCompatibleString(const SString &s, SString &scratch) const; const SString &GetCompatibleString(const SString &s, SString &scratch, const CIterator &i) const; diff --git a/src/coreclr/inc/sstring.inl b/src/coreclr/inc/sstring.inl index 0d48c5a181db4..03fc26fe9666c 100644 --- a/src/coreclr/inc/sstring.inl +++ b/src/coreclr/inc/sstring.inl @@ -651,25 +651,6 @@ inline const WCHAR *SString::GetUnicode() const SS_RETURN GetRawUnicode(); } -// Get a const pointer to the internal buffer as a UTF8 string. -inline const UTF8 *SString::GetUTF8() const -{ - SS_CONTRACT(const UTF8 *) - { - GC_NOTRIGGER; - PRECONDITION(CheckPointer(this)); - SS_POSTCONDITION(CheckPointer(RETVAL)); - if (IsRepresentation(REPRESENTATION_UTF8)) NOTHROW; else THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC; - } - SS_CONTRACT_END; - - ConvertToUTF8(); - - SS_RETURN GetRawUTF8(); -} - // Normalize the string to unicode. This will make many operations nonfailing. inline void SString::Normalize() const { @@ -1925,6 +1906,44 @@ inline void SString::ConvertToIteratable() const SS_RETURN; } +//----------------------------------------------------------------------------- +// Create iterators on the string. +//----------------------------------------------------------------------------- + +inline SString::UIterator SString::BeginUnicode() +{ + SS_CONTRACT(SString::UIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; + } + SS_CONTRACT_END; + + ConvertToUnicode(); + EnsureWritable(); + + SS_RETURN UIterator(this, 0); +} + +inline SString::UIterator SString::EndUnicode() +{ + SS_CONTRACT(SString::UIterator) + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(this)); + SS_POSTCONDITION(CheckValue(RETVAL)); + THROWS; + } + SS_CONTRACT_END; + + ConvertToUnicode(); + EnsureWritable(); + + SS_RETURN UIterator(this, GetCount()); +} + //----------------------------------------------------------------------------- // Create CIterators on the string. //----------------------------------------------------------------------------- @@ -2116,6 +2135,74 @@ inline WCHAR SString::Index::operator[](int index) const return *(WCHAR*)&GetAt(index); } +//----------------------------------------------------------------------------- +// Iterator support routines +//----------------------------------------------------------------------------- + +inline SString::UIndex::UIndex() +{ + LIMITED_METHOD_CONTRACT; +} + +inline SString::UIndex::UIndex(SString *string, SCOUNT_T index) + : SBuffer::Index(string, index*sizeof(WCHAR)) +{ + SS_CONTRACT_VOID + { + GC_NOTRIGGER; + PRECONDITION(CheckPointer(string)); + PRECONDITION(string->IsRepresentation(REPRESENTATION_UNICODE)); + PRECONDITION(DoCheck(0)); + SS_POSTCONDITION(CheckPointer(this)); + NOTHROW; + CANNOT_TAKE_LOCK; + } + SS_CONTRACT_END; + + SS_RETURN; +} + +inline WCHAR &SString::UIndex::GetAt(SCOUNT_T delta) const +{ + LIMITED_METHOD_CONTRACT; + + return ((WCHAR*)m_ptr)[delta]; +} + +inline void SString::UIndex::Skip(SCOUNT_T delta) +{ + LIMITED_METHOD_CONTRACT; + + m_ptr += delta * sizeof(WCHAR); +} + +inline SCOUNT_T SString::UIndex::Subtract(const UIndex &i) const +{ + WRAPPER_NO_CONTRACT; + + return (SCOUNT_T) (GetUnicode() - i.GetUnicode()); +} + +inline CHECK SString::UIndex::DoCheck(SCOUNT_T delta) const +{ + CANNOT_HAVE_CONTRACT; +#if _DEBUG + const SString *string = (const SString *) GetContainerDebug(); + + CHECK(GetUnicode() + delta >= string->GetRawUnicode()); + CHECK(GetUnicode() + delta <= string->GetRawUnicode() + string->GetCount()); +#endif + + CHECK_OK; +} + +inline WCHAR *SString::UIndex::GetUnicode() const +{ + LIMITED_METHOD_CONTRACT; + + return (WCHAR*) m_ptr; +} + //----------------------------------------------------------------------------- // Opaque scratch buffer class routines //----------------------------------------------------------------------------- diff --git a/src/coreclr/inc/static_assert.h b/src/coreclr/inc/static_assert.h index 67336e1290394..e344e83baca55 100644 --- a/src/coreclr/inc/static_assert.h +++ b/src/coreclr/inc/static_assert.h @@ -14,6 +14,12 @@ #ifndef __STATIC_ASSERT_H__ #define __STATIC_ASSERT_H__ +// static_assert( cond, msg ) is now a compiler-supported intrinsic in Dev10 C++ compiler. +// Replaces previous uses of STATIC_ASSERT_MSG and COMPILE_TIME_ASSERT_MSG. + +// Replaces previous uses of CPP_ASSERT +#define static_assert_n( n, cond ) static_assert( cond, #cond ) + // Replaces previous uses of C_ASSERT and COMPILE_TIME_ASSERT #define static_assert_no_msg( cond ) static_assert( cond, #cond ) diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 9ec7e3cf05efd..d3fe1d636440d 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -53,7 +53,7 @@ #if defined(TARGET_X86) || defined(TARGET_ARM) #define USE_LAZY_PREFERRED_RANGE 0 -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) || defined(TARGET_POWERPC64) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) #if defined(HOST_UNIX) // In PAL we have a smechanism that reserves memory on start up that is diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index f9444ab439ae6..7191833998d4d 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -3808,6 +3808,14 @@ inline bool FitsInRel28(INT64 val64) return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL); } +//***************************************************************************** +// Splits a command line into argc/argv lists, using the VC7 parsing rules. +// This functions interface mimics the CommandLineToArgvW api. +// If function fails, returns NULL. +// If function suceeds, call delete [] on return pointer when done. +//***************************************************************************** +LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs); + // // TEB access can be dangerous when using fibers because a fiber may // run on multiple threads. If the TEB pointer is retrieved and saved @@ -3832,6 +3840,11 @@ class ClrTeb return (void *)(size_t)GetCurrentThreadId(); } + static void* InvalidFiberPtrId() + { + return NULL; + } + static void* GetStackBase() { return PAL_GetStackBase(); @@ -3864,12 +3877,33 @@ class ClrTeb return NtCurrentTeb()->NtTib.StackLimit; } + // Please don't start to use this method unless you absolutely have to. + // The reason why this is added is for WIN64 to support LEGACY PE-style TLS + // variables. On X86 it is supported by the JIT compilers themselves. On + // WIN64 we build more logic into the JIT helper for accessing fields. + static void* GetLegacyThreadLocalStoragePointer() + { + LIMITED_METHOD_CONTRACT; + return NtCurrentTeb()->ThreadLocalStoragePointer; + } + static void* GetOleReservedPtr() { LIMITED_METHOD_CONTRACT; return NtCurrentTeb()->ReservedForOle; } + static void* GetProcessEnvironmentBlock() + { + LIMITED_METHOD_CONTRACT; + return NtCurrentTeb()->ProcessEnvironmentBlock; + } + + + static void* InvalidFiberPtrId() + { + return (void*) 1; + } #endif // HOST_UNIX }; diff --git a/src/coreclr/inc/volatile.h b/src/coreclr/inc/volatile.h index 5f3f7491facef..dcfc8af4b329e 100644 --- a/src/coreclr/inc/volatile.h +++ b/src/coreclr/inc/volatile.h @@ -68,8 +68,8 @@ #error The Volatile type is currently only defined for Visual C++ and GNU C++ #endif -#if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64) && !defined(HOST_LOONGARCH64) && !defined(HOST_S390X) && !defined(HOST_POWERPC64) -#error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM, ARM64, LOONGARCH64, PPC64LE, or S390X CPUs +#if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64) && !defined(HOST_LOONGARCH64) && !defined(HOST_S390X) +#error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM, ARM64, LOONGARCH64, or S390X CPUs #endif #if defined(__GNUC__) diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index 3410747d021eb..4bc1693e8dfb7 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -48,9 +48,6 @@ function(create_standalone_jit) elseif(TARGETDETAILS_ARCH STREQUAL "s390x") set(JIT_ARCH_SOURCES ${JIT_S390X_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_S390X_HEADERS}) - elseif(TARGETDETAILS_ARCH STREQUAL "ppc64le") - set(JIT_ARCH_SOURCES ${JIT_POWERPC64_SOURCES}) - set(JIT_ARCH_HEADERS ${JIT_POWERPC64_HEADERS}) elseif(TARGETDETAILS_ARCH STREQUAL "loongarch64") set(JIT_ARCH_SOURCES ${JIT_LOONGARCH64_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_LOONGARCH64_HEADERS}) @@ -244,10 +241,6 @@ set( JIT_S390X_SOURCES # Not supported as JIT target ) -set( JIT_POWERPC64_SOURCES - # Not supported as JIT target -) - set( JIT_LOONGARCH64_SOURCES codegenloongarch64.cpp emitloongarch64.cpp @@ -403,10 +396,6 @@ set ( JIT_S390X_HEADERS # Not supported as JIT target ) -set ( JIT_POWERPC64_HEADERS - # Not supported as JIT target -) - set( JIT_LOONGARCH64_HEADERS emitloongarch64.h emitfmtsloongarch64.h @@ -453,9 +442,6 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM64) elseif(CLR_CMAKE_TARGET_ARCH_S390X) set(JIT_ARCH_SOURCES ${JIT_S390X_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_S390X_HEADERS}) -elseif(CLR_CMAKE_TARGET_ARCH_POWERPC64) - set(JIT_ARCH_SOURCES ${JIT_POWERPC64_SOURCES}) - set(JIT_ARCH_HEADERS ${JIT_POWERPC64_HEADERS}) elseif(CLR_CMAKE_TARGET_ARCH_LOONGARCH64) set(JIT_ARCH_SOURCES ${JIT_LOONGARCH64_SOURCES}) set(JIT_ARCH_HEADERS ${JIT_LOONGARCH64_HEADERS}) @@ -614,13 +600,13 @@ if (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX) endif (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX) if (CLR_CMAKE_TARGET_UNIX) - if (NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6 AND NOT ARCH_TARGET_NAME STREQUAL ppc64le) + if (NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6) if(CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64) install_clr(TARGETS clrjit_universal_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME} DESTINATIONS . COMPONENT jit) else() install_clr(TARGETS clrjit_unix_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME} DESTINATIONS . COMPONENT jit) endif() - endif(NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6 AND NOT ARCH_TARGET_NAME STREQUAL ppc64le) + endif(NOT ARCH_TARGET_NAME STREQUAL s390x AND NOT ARCH_TARGET_NAME STREQUAL armv6) endif() if (CLR_CMAKE_TARGET_WIN32 AND CLR_CMAKE_PGO_INSTRUMENT) diff --git a/src/coreclr/jit/ClrJit.PAL.exports b/src/coreclr/jit/ClrJit.PAL.exports index e4e6064db84e8..2625e98bc421e 100644 --- a/src/coreclr/jit/ClrJit.PAL.exports +++ b/src/coreclr/jit/ClrJit.PAL.exports @@ -1,5 +1,4 @@ getJit jitStartup getLikelyClasses -getLikelyMethods jitBuildString diff --git a/src/coreclr/jit/ClrJit.exports b/src/coreclr/jit/ClrJit.exports index 5430f7b165929..c6a22db4cae40 100644 --- a/src/coreclr/jit/ClrJit.exports +++ b/src/coreclr/jit/ClrJit.exports @@ -5,5 +5,4 @@ EXPORTS getJit jitStartup getLikelyClasses - getLikelyMethods jitBuildString diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index 2549835cefbf8..520315b89f82a 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -10,7 +10,6 @@ DEF_CLR_API(setMethodAttribs) DEF_CLR_API(getMethodSig) DEF_CLR_API(getMethodInfo) DEF_CLR_API(canInline) -DEF_CLR_API(beginInlining) DEF_CLR_API(reportInliningDecision) DEF_CLR_API(canTailCall) DEF_CLR_API(reportTailCallDecision) diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index f6a7b39b1590a..e65d1be26b3a0 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -69,15 +69,6 @@ CorInfoInline WrapICorJitInfo::canInline( return temp; } -void WrapICorJitInfo::beginInlining( - CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) -{ - API_ENTER(beginInlining); - wrapHnd->beginInlining(inlinerHnd, inlineeHnd); - API_LEAVE(beginInlining); -} - void WrapICorJitInfo::reportInliningDecision( CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index ccade20df0fbc..ddee8ba3e6e1b 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1344,12 +1344,12 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, if (op1->gtGetOp2()->IsCnsIntOrI()) { offset += op1->gtGetOp2()->AsIntCon()->gtIconVal; - op1 = op1->gtGetOp1()->gtEffectiveVal(/* commaOnly */ true); + op1 = op1->gtGetOp1(); } else if (op1->gtGetOp1()->IsCnsIntOrI()) { offset += op1->gtGetOp1()->AsIntCon()->gtIconVal; - op1 = op1->gtGetOp2()->gtEffectiveVal(/* commaOnly */ true); + op1 = op1->gtGetOp2(); } else { @@ -1431,6 +1431,9 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, assertion.op2.vn = ValueNumStore::VNForNull(); assertion.op2.u1.iconVal = 0; assertion.op2.u1.iconFlags = GTF_EMPTY; +#ifdef TARGET_64BIT + assertion.op2.u1.iconFlags |= GTF_ASSERTION_PROP_LONG; // Signify that this is really TYP_LONG +#endif // TARGET_64BIT } // // Are we making an assertion about a local variable? @@ -1565,6 +1568,13 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, #endif // TARGET_ARM assertion.op2.u1.iconVal = op2->AsIntCon()->gtIconVal; assertion.op2.u1.iconFlags = op2->GetIconHandleFlag(); +#ifdef TARGET_64BIT + if (op2->TypeGet() == TYP_LONG || op2->TypeGet() == TYP_BYREF) + { + assertion.op2.u1.iconFlags |= + GTF_ASSERTION_PROP_LONG; // Signify that this is really TYP_LONG + } +#endif // TARGET_64BIT } else if (op2->gtOper == GT_CNS_LNG) { @@ -1721,6 +1731,12 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, /* iconFlags should only contain bits in GTF_ICON_HDL_MASK */ assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0); assertion.op2.u1.iconFlags = iconFlags; +#ifdef TARGET_64BIT + if (op2->AsOp()->gtOp1->TypeGet() == TYP_LONG) + { + assertion.op2.u1.iconFlags |= GTF_ASSERTION_PROP_LONG; // Signify that this is really TYP_LONG + } +#endif // TARGET_64BIT } // JIT case else if (optIsTreeKnownIntValue(!optLocalAssertionProp, op2, &cnsValue, &iconFlags)) @@ -1733,6 +1749,12 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, /* iconFlags should only contain bits in GTF_ICON_HDL_MASK */ assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0); assertion.op2.u1.iconFlags = iconFlags; +#ifdef TARGET_64BIT + if (op2->TypeGet() == TYP_LONG) + { + assertion.op2.u1.iconFlags |= GTF_ASSERTION_PROP_LONG; // Signify that this is really TYP_LONG + } +#endif // TARGET_64BIT } else { @@ -2025,9 +2047,13 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) case O2K_IND_CNS_INT: case O2K_CONST_INT: { - // The only flags that can be set are those in the GTF_ICON_HDL_MASK. +// The only flags that can be set are those in the GTF_ICON_HDL_MASK, or GTF_ASSERTION_PROP_LONG, which is +// used to indicate a long constant. +#ifdef TARGET_64BIT + assert((assertion->op2.u1.iconFlags & ~(GTF_ICON_HDL_MASK | GTF_ASSERTION_PROP_LONG)) == 0); +#else assert((assertion->op2.u1.iconFlags & ~GTF_ICON_HDL_MASK) == 0); - +#endif switch (assertion->op1.kind) { case O1K_EXACT_TYPE: @@ -3151,15 +3177,6 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) if (conValTree != nullptr) { - if (tree->OperIs(GT_LCL_VAR)) - { - if (!optIsProfitableToSubstitute(tree->AsLclVar(), block, conValTree)) - { - // Not profitable to substitute - return nullptr; - } - } - // Were able to optimize. conValTree->gtVNPair = vnPair; GenTree* sideEffList = optExtractSideEffListFromConst(tree); @@ -3182,55 +3199,6 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree) } } -//------------------------------------------------------------------------------ -// optIsProfitableToSubstitute: Checks if value worth substituting to lcl location -// -// Arguments: -// lcl - lcl to replace with value if profitable -// lclBlock - Basic block lcl located in -// value - value we plan to substitute to lcl -// -// Returns: -// False if it's likely not profitable to do substitution, True otherwise -// -bool Compiler::optIsProfitableToSubstitute(GenTreeLclVarCommon* lcl, BasicBlock* lclBlock, GenTree* value) -{ - // A simple heuristic: If the constant is defined outside of a loop (not far from its head) - // and is used inside it - don't propagate. - - // TODO: Extend on more kinds of trees - if (!value->OperIs(GT_CNS_VEC, GT_CNS_DBL)) - { - return true; - } - - gtPrepareCost(value); - - if ((value->GetCostEx() > 1) && (value->GetCostSz() > 1)) - { - // Try to find the block this constant was originally defined in - if (lcl->HasSsaName()) - { - BasicBlock* defBlock = lvaGetDesc(lcl)->GetPerSsaData(lcl->GetSsaNum())->GetBlock(); - if (defBlock != nullptr) - { - // Avoid propagating if the weighted use cost is significantly greater than the def cost. - // NOTE: this currently does not take "a float living across a call" case into account - // where we might end up with spill/restore on ABIs without callee-saved registers - const weight_t defBlockWeight = defBlock->getBBWeight(this); - const weight_t lclblockWeight = lclBlock->getBBWeight(this); - - if ((defBlockWeight > 0) && ((lclblockWeight / defBlockWeight) >= BB_LOOP_WEIGHT_SCALE)) - { - JITDUMP("Constant propagation inside loop " FMT_BB " is not profitable\n", lclBlock->bbNum); - return false; - } - } - } - } - return true; -} - //------------------------------------------------------------------------------ // optConstantAssertionProp: Possibly substitute a constant for a local use // diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index e9a539a2f35fa..88dcb79794fb8 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -526,32 +526,32 @@ enum BasicBlockFlags : unsigned __int64 #endif // defined(FEATURE_EH_FUNCLETS) && defined(TARGET_ARM) - BBF_BACKWARD_JUMP = MAKE_BBFLAG(24), // BB is surrounded by a backward jump/switch arc - BBF_RETLESS_CALL = MAKE_BBFLAG(25), // BBJ_CALLFINALLY that will never return (and therefore, won't need a paired - // BBJ_ALWAYS); see isBBCallAlwaysPair(). - BBF_LOOP_PREHEADER = MAKE_BBFLAG(26), // BB is a loop preheader block - BBF_COLD = MAKE_BBFLAG(27), // BB is cold - - BBF_PROF_WEIGHT = MAKE_BBFLAG(28), // BB weight is computed from profile data - BBF_IS_LIR = MAKE_BBFLAG(29), // Set if the basic block contains LIR (as opposed to HIR) - BBF_KEEP_BBJ_ALWAYS = MAKE_BBFLAG(30), // A special BBJ_ALWAYS block, used by EH code generation. Keep the jump kind - // as BBJ_ALWAYS. Used for the paired BBJ_ALWAYS block following the - // BBJ_CALLFINALLY block, as well as, on x86, the final step block out of a - // finally. - BBF_CLONED_FINALLY_BEGIN = MAKE_BBFLAG(31), // First block of a cloned finally region - - BBF_CLONED_FINALLY_END = MAKE_BBFLAG(32), // Last block of a cloned finally region - BBF_HAS_CALL = MAKE_BBFLAG(33), // BB contains a call + BBF_BACKWARD_JUMP = MAKE_BBFLAG(24), // BB is surrounded by a backward jump/switch arc + BBF_RETLESS_CALL = MAKE_BBFLAG(25), // BBJ_CALLFINALLY that will never return (and therefore, won't need a paired + // BBJ_ALWAYS); see isBBCallAlwaysPair(). + BBF_LOOP_PREHEADER = MAKE_BBFLAG(26), // BB is a loop preheader block + BBF_COLD = MAKE_BBFLAG(27), // BB is cold + + BBF_PROF_WEIGHT = MAKE_BBFLAG(28), // BB weight is computed from profile data + BBF_IS_LIR = MAKE_BBFLAG(29), // Set if the basic block contains LIR (as opposed to HIR) + BBF_KEEP_BBJ_ALWAYS = MAKE_BBFLAG(30), // A special BBJ_ALWAYS block, used by EH code generation. Keep the jump kind + // as BBJ_ALWAYS. Used for the paired BBJ_ALWAYS block following the + // BBJ_CALLFINALLY block, as well as, on x86, the final step block out of a + // finally. + BBF_CLONED_FINALLY_BEGIN = MAKE_BBFLAG(31), // First block of a cloned finally region + + BBF_CLONED_FINALLY_END = MAKE_BBFLAG(32), // Last block of a cloned finally region + BBF_HAS_CALL = MAKE_BBFLAG(33), // BB contains a call BBF_DOMINATED_BY_EXCEPTIONAL_ENTRY = MAKE_BBFLAG(34), // Block is dominated by exceptional entry. - BBF_BACKWARD_JUMP_TARGET = MAKE_BBFLAG(35), // Block is a target of a backward jump + BBF_BACKWARD_JUMP_TARGET = MAKE_BBFLAG(35), // Block is a target of a backward jump - BBF_PATCHPOINT = MAKE_BBFLAG(36), // Block is a patchpoint - BBF_HAS_HISTOGRAM_PROFILE = MAKE_BBFLAG(37), // BB contains a call needing a histogram profile - BBF_PARTIAL_COMPILATION_PATCHPOINT = MAKE_BBFLAG(38), // Block is a partial compilation patchpoint - BBF_HAS_ALIGN = MAKE_BBFLAG(39), // BB ends with 'align' instruction - BBF_TAILCALL_SUCCESSOR = MAKE_BBFLAG(40), // BB has pred that has potential tail call + BBF_PATCHPOINT = MAKE_BBFLAG(36), // Block is a patchpoint + BBF_HAS_CLASS_PROFILE = MAKE_BBFLAG(37), // BB contains a call needing a class profile + BBF_PARTIAL_COMPILATION_PATCHPOINT = MAKE_BBFLAG(38), // Block is a partial compilation patchpoint + BBF_HAS_ALIGN = MAKE_BBFLAG(39), // BB ends with 'align' instruction + BBF_TAILCALL_SUCCESSOR = MAKE_BBFLAG(40), // BB has pred that has potential tail call - BBF_BACKWARD_JUMP_SOURCE = MAKE_BBFLAG(41), // Block is a source of a backward jump + BBF_BACKWARD_JUMP_SOURCE = MAKE_BBFLAG(41), // Block is a source of a backward jump // The following are sets of flags. @@ -582,7 +582,7 @@ enum BasicBlockFlags : unsigned __int64 // TODO: Should BBF_RUN_RARELY be added to BBF_SPLIT_GAINED ? BBF_SPLIT_GAINED = BBF_DONT_REMOVE | BBF_HAS_JMP | BBF_BACKWARD_JUMP | BBF_HAS_IDX_LEN | BBF_HAS_NEWARRAY | BBF_PROF_WEIGHT | \ - BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_NULLCHECK | BBF_HAS_HISTOGRAM_PROFILE, + BBF_HAS_NEWOBJ | BBF_KEEP_BBJ_ALWAYS | BBF_CLONED_FINALLY_END | BBF_HAS_NULLCHECK | BBF_HAS_CLASS_PROFILE, }; inline constexpr BasicBlockFlags operator ~(BasicBlockFlags a) @@ -918,8 +918,8 @@ struct BasicBlock : private LIR::Range }; union { - unsigned bbStkTempsOut; // base# for output stack temps - int bbHistogramSchemaIndex; // schema index for histogram instrumentation + unsigned bbStkTempsOut; // base# for output stack temps + int bbClassSchemaIndex; // schema index for class instrumentation }; #define MAX_XCPTN_INDEX (USHRT_MAX - 1) diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index c294957a0cd2c..8646d9191edcf 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -642,7 +642,6 @@ class CodeGen final : public CodeGenInterface virtual void SetSaveFpLrWithAllCalleeSavedRegisters(bool value); virtual bool IsSaveFpLrWithAllCalleeSavedRegisters() const; bool genSaveFpLrWithAllCalleeSavedRegisters; - bool genForceFuncletFrameType5; #endif // TARGET_ARM64 //------------------------------------------------------------------------- @@ -1336,10 +1335,10 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void genPutStructArgStk(GenTreePutArgStk* treeNode); - unsigned genMove8IfNeeded(unsigned size, regNumber tmpReg, GenTree* src, unsigned offset); - unsigned genMove4IfNeeded(unsigned size, regNumber tmpReg, GenTree* src, unsigned offset); - unsigned genMove2IfNeeded(unsigned size, regNumber tmpReg, GenTree* src, unsigned offset); - unsigned genMove1IfNeeded(unsigned size, regNumber tmpReg, GenTree* src, unsigned offset); + unsigned genMove8IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); + unsigned genMove4IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); + unsigned genMove2IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); + unsigned genMove1IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset); void genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* base, unsigned offset); void genStoreRegToStackArg(var_types type, regNumber reg, int offset); void genStructPutArgRepMovs(GenTreePutArgStk* putArgStkNode); diff --git a/src/coreclr/jit/codegenarm64.cpp b/src/coreclr/jit/codegenarm64.cpp index b13c11c50d668..2b9d4be0abc7d 100644 --- a/src/coreclr/jit/codegenarm64.cpp +++ b/src/coreclr/jit/codegenarm64.cpp @@ -186,7 +186,6 @@ void CodeGen::genPopCalleeSavedRegistersAndFreeLclFrame(bool jmpEpilog) JITDUMP("Frame type 5 (save FP/LR at top). #outsz=%d; #framesz=%d; localloc? %s\n", unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, dspBool(compiler->compLocallocUsed)); - assert(genSaveFpLrWithAllCalleeSavedRegisters); assert((calleeSaveSpOffset == 0) || (calleeSaveSpOffset == REGSIZE_BYTES)); // Restore sp from fp: @@ -1078,14 +1077,10 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | OSR padding | // If required - * |-----------------------| * | Varargs regs space | // Only for varargs main functions; 64 bytes * |-----------------------| * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | MonitorAcquired | // 8 bytes; for synchronized methods - * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned. @@ -1109,14 +1104,10 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | OSR padding | // If required - * |-----------------------| * | Varargs regs space | // Only for varargs main functions; 64 bytes * |-----------------------| * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | MonitorAcquired | // 8 bytes; for synchronized methods - * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned. @@ -1143,24 +1134,20 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | OSR padding | // If required - * |-----------------------| * | Varargs regs space | // Only for varargs main functions; 64 bytes * |-----------------------| * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | MonitorAcquired | // 8 bytes; for synchronized methods - * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| * ~ alignment padding ~ // To make the first SP subtraction 16 byte aligned * |-----------------------| - * | Saved FP, LR | // 16 bytes <-- SP after first adjustment (points at saved FP) + * | Saved FP, LR | // 16 bytes * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned (specifically, to 16-byte align the outgoing argument space). * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes - * |-----------------------| <---- Ambient SP (SP after second adjustment) + * |-----------------------| <---- Ambient SP * | | | * ~ | Stack grows ~ * | | downward | @@ -1175,7 +1162,7 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * 8 float callee-saved registers v8-v15 * 8 saved integer argument registers x0-x7, if varargs function * 1 PSP slot - * 1 alignment slot or monitor acquired slot + * 1 alignment slot * == 30 slots * 8 bytes = 240 bytes. * * The outgoing argument size, however, can be very large, if we call a function that takes a large number of @@ -1211,8 +1198,6 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | OSR padding | // If required - * |-----------------------| * | Varargs regs space | // Only for varargs main functions; 64 bytes * |-----------------------| * | Saved LR | // 8 bytes @@ -1221,8 +1206,6 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | MonitorAcquired | // 8 bytes; for synchronized methods - * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned. @@ -1252,8 +1235,6 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | OSR padding | // If required - * |-----------------------| * | Varargs regs space | // Only for varargs main functions; 64 bytes * |-----------------------| * | Saved LR | // 8 bytes @@ -1262,16 +1243,14 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * |-----------------------| * |Callee saved registers | // multiple of 8 bytes * |-----------------------| - * | MonitorAcquired | // 8 bytes; for synchronized methods - * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| - * ~ alignment padding ~ // To make the first SP subtraction 16 byte aligned <-- SP after first adjustment (points at alignment padding or PSP slot) + * ~ alignment padding ~ // To make the first SP subtraction 16 byte aligned * |-----------------------| * ~ alignment padding ~ // To make the whole frame 16 byte aligned (specifically, to 16-byte align the outgoing argument space). * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes - * |-----------------------| <---- Ambient SP (SP after second adjustment) + * |-----------------------| <---- Ambient SP * | | | * ~ | Stack grows ~ * | | downward | @@ -1331,8 +1310,6 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * ldp fp,lr,[sp],#framesz * ret lr * - * See CodeGen::genPushCalleeSavedRegisters() for a description of the main function frame layout. - * See Compiler::lvaAssignVirtualFrameOffsetsToLocals() for calculation of main frame local variable offsets. */ // clang-format on @@ -1377,12 +1354,10 @@ void CodeGen::genFuncletProlog(BasicBlock* block) if (genFuncletInfo.fiFrameType == 1) { + // With OSR we may see large values for fiSpDelta1 + // (we really need to probe the frame, sigh) if (compiler->opts.IsOSR()) { - // With OSR we may see large values for fiSpDelta1. - // We repurpose genAllocLclFram to do the necessary probing. - bool scratchRegIsZero = false; - genAllocLclFrame(-genFuncletInfo.fiSpDelta1, REG_SCRATCH, &scratchRegIsZero, maskArgRegsLiveIn); genStackPointerAdjustment(genFuncletInfo.fiSpDelta1, REG_SCRATCH, nullptr, /* reportUnwindData */ true); GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0); compiler->unwindSaveRegPair(REG_FP, REG_LR, 0); @@ -1418,12 +1393,10 @@ void CodeGen::genFuncletProlog(BasicBlock* block) } else if (genFuncletInfo.fiFrameType == 3) { + // With OSR we may see large values for fiSpDelta1 + // (we really need to probe the frame, sigh) if (compiler->opts.IsOSR()) { - // With OSR we may see large values for fiSpDelta1 - // We repurpose genAllocLclFram to do the necessary probing. - bool scratchRegIsZero = false; - genAllocLclFrame(-genFuncletInfo.fiSpDelta1, REG_SCRATCH, &scratchRegIsZero, maskArgRegsLiveIn); genStackPointerAdjustment(genFuncletInfo.fiSpDelta1, REG_SCRATCH, nullptr, /* reportUnwindData */ true); GetEmitter()->emitIns_R_R_R_I(INS_stp, EA_PTRSIZE, REG_FP, REG_LR, REG_SPBASE, 0); compiler->unwindSaveRegPair(REG_FP, REG_LR, 0); @@ -1454,17 +1427,11 @@ void CodeGen::genFuncletProlog(BasicBlock* block) if (compiler->opts.IsOSR()) { - // With OSR we may see large values for fiSpDelta1. - // We repurpose genAllocLclFram to do the necessary probing. - bool scratchRegIsZero = false; - genAllocLclFrame(-genFuncletInfo.fiSpDelta1, REG_SCRATCH, &scratchRegIsZero, maskArgRegsLiveIn); genStackPointerAdjustment(genFuncletInfo.fiSpDelta1, REG_SCRATCH, nullptr, /* reportUnwindData */ true); } else { - assert(genFuncletInfo.fiSpDelta1 < 0); - assert(genFuncletInfo.fiSpDelta1 >= -240); - genStackPointerAdjustment(genFuncletInfo.fiSpDelta1, REG_NA, nullptr, /* reportUnwindData */ true); + // Nothing to do here; the first SP adjustment will be done by saving the callee-saved registers. } } @@ -1534,8 +1501,6 @@ void CodeGen::genFuncletProlog(BasicBlock* block) /***************************************************************************** * * Generates code for an EH funclet epilog. - * - * See the description of frame shapes at genFuncletProlog(). */ void CodeGen::genFuncletEpilog() @@ -1710,9 +1675,6 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() if (compiler->opts.IsOSR() && (PSPSize > 0)) { osrPad = compiler->info.compPatchpointInfo->TotalFrameSize(); - - // OSR pad must be already aligned to stack size. - assert((osrPad % STACK_ALIGN) == 0); } genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta() - osrPad; @@ -1743,41 +1705,31 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0); unsigned const outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); - // If do two SP adjustments, each one must be aligned. This represents the largest possible stack size, if two - // separate alignment slots are required. - unsigned const twoSpAdjustmentFuncletFrameSizeAligned = - osrPad + saveRegsPlusPSPSizeAligned + outgoingArgSpaceAligned; - assert((twoSpAdjustmentFuncletFrameSizeAligned % STACK_ALIGN) == 0); + unsigned const maxFuncletFrameSizeAligned = saveRegsPlusPSPSizeAligned + osrPad + outgoingArgSpaceAligned; + assert((maxFuncletFrameSizeAligned % STACK_ALIGN) == 0); int SP_to_FPLR_save_delta; int SP_to_PSP_slot_delta; int CallerSP_to_PSP_slot_delta; - // Are we stressing frame type 5? Don't do it unless we have non-zero outgoing arg space. - const bool useFrameType5 = - genSaveFpLrWithAllCalleeSavedRegisters && genForceFuncletFrameType5 && (compiler->lvaOutgoingArgSpaceSize > 0); + unsigned const funcletFrameSize = saveRegsPlusPSPSize + osrPad + compiler->lvaOutgoingArgSpaceSize; + unsigned const funcletFrameSizeAligned = roundUp(funcletFrameSize, STACK_ALIGN); + assert(funcletFrameSizeAligned <= maxFuncletFrameSizeAligned); - if ((twoSpAdjustmentFuncletFrameSizeAligned <= 512) && !useFrameType5) - { - unsigned const oneSpAdjustmentFuncletFrameSize = - osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize; - unsigned const oneSpAdjustmentFuncletFrameSizeAligned = roundUp(oneSpAdjustmentFuncletFrameSize, STACK_ALIGN); - assert(oneSpAdjustmentFuncletFrameSizeAligned <= twoSpAdjustmentFuncletFrameSizeAligned); - - unsigned const oneSpAdjustmentFuncletFrameSizeAlignmentPad = - oneSpAdjustmentFuncletFrameSizeAligned - oneSpAdjustmentFuncletFrameSize; - assert((oneSpAdjustmentFuncletFrameSizeAlignmentPad == 0) || - (oneSpAdjustmentFuncletFrameSizeAlignmentPad == REGSIZE_BYTES)); + unsigned const funcletFrameAlignmentPad = funcletFrameSizeAligned - funcletFrameSize; + assert((funcletFrameAlignmentPad == 0) || (funcletFrameAlignmentPad == REGSIZE_BYTES)); + if (maxFuncletFrameSizeAligned <= 512) + { if (genSaveFpLrWithAllCalleeSavedRegisters) { - SP_to_FPLR_save_delta = oneSpAdjustmentFuncletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES); + SP_to_FPLR_save_delta = funcletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES); if (compiler->info.compIsVarArgs) { SP_to_FPLR_save_delta -= MAX_REG_ARG * REGSIZE_BYTES; } - SP_to_PSP_slot_delta = compiler->lvaOutgoingArgSpaceSize + oneSpAdjustmentFuncletFrameSizeAlignmentPad; + SP_to_PSP_slot_delta = compiler->lvaOutgoingArgSpaceSize + funcletFrameAlignmentPad + osrPad; CallerSP_to_PSP_slot_delta = -(int)(osrPad + saveRegsPlusPSPSize); genFuncletInfo.fiFrameType = 4; @@ -1785,8 +1737,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() else { SP_to_FPLR_save_delta = compiler->lvaOutgoingArgSpaceSize; - SP_to_PSP_slot_delta = - SP_to_FPLR_save_delta + 2 /* FP, LR */ * REGSIZE_BYTES + oneSpAdjustmentFuncletFrameSizeAlignmentPad; + SP_to_PSP_slot_delta = SP_to_FPLR_save_delta + 2 /* FP, LR */ * REGSIZE_BYTES + funcletFrameAlignmentPad; CallerSP_to_PSP_slot_delta = -(int)(osrPad + saveRegsPlusPSPSize - 2 /* FP, LR */ * REGSIZE_BYTES); if (compiler->lvaOutgoingArgSpaceSize == 0) @@ -1799,25 +1750,26 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() } } - genFuncletInfo.fiSpDelta1 = -(int)oneSpAdjustmentFuncletFrameSizeAligned; + genFuncletInfo.fiSpDelta1 = -(int)funcletFrameSizeAligned; genFuncletInfo.fiSpDelta2 = 0; - assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)oneSpAdjustmentFuncletFrameSizeAligned); + assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)funcletFrameSizeAligned); } else { - unsigned const saveRegsPlusPSPAlignmentPad = saveRegsPlusPSPSizeAligned - saveRegsPlusPSPSize; + unsigned saveRegsPlusPSPAlignmentPad = saveRegsPlusPSPSizeAligned - saveRegsPlusPSPSize; assert((saveRegsPlusPSPAlignmentPad == 0) || (saveRegsPlusPSPAlignmentPad == REGSIZE_BYTES)); if (genSaveFpLrWithAllCalleeSavedRegisters) { - SP_to_FPLR_save_delta = twoSpAdjustmentFuncletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES); + SP_to_FPLR_save_delta = funcletFrameSizeAligned - (2 /* FP, LR */ * REGSIZE_BYTES); if (compiler->info.compIsVarArgs) { SP_to_FPLR_save_delta -= MAX_REG_ARG * REGSIZE_BYTES; } - SP_to_PSP_slot_delta = outgoingArgSpaceAligned + saveRegsPlusPSPAlignmentPad; + SP_to_PSP_slot_delta = + compiler->lvaOutgoingArgSpaceSize + funcletFrameAlignmentPad + saveRegsPlusPSPAlignmentPad; CallerSP_to_PSP_slot_delta = -(int)(osrPad + saveRegsPlusPSPSize); genFuncletInfo.fiFrameType = 5; @@ -1835,7 +1787,7 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() genFuncletInfo.fiSpDelta1 = -(int)(osrPad + saveRegsPlusPSPSizeAligned); genFuncletInfo.fiSpDelta2 = -(int)outgoingArgSpaceAligned; - assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)twoSpAdjustmentFuncletFrameSizeAligned); + assert(genFuncletInfo.fiSpDelta1 + genFuncletInfo.fiSpDelta2 == -(int)maxFuncletFrameSizeAligned); } /* Now save it for future use */ @@ -2226,7 +2178,7 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, { if (emitter::emitIns_valid_imm_for_mov(imm, size)) { - GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm, INS_OPTS_NONE DEBUGARG(targetHandle) DEBUGARG(gtFlags)); + GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm); } else { @@ -2272,9 +2224,7 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, imm16 = ~imm16; } - GetEmitter()->emitIns_R_I_I(ins, size, reg, imm16, i, - INS_OPTS_LSL DEBUGARG(i == 0 ? targetHandle : 0) - DEBUGARG(i == 0 ? gtFlags : GTF_EMPTY)); + GetEmitter()->emitIns_R_I_I(ins, size, reg, imm16, i, INS_OPTS_LSL); // Once the initial movz/movn is emitted the remaining instructions will all use movk ins = INS_movk; @@ -2308,8 +2258,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre { case GT_CNS_INT: { - GenTreeIntCon* con = tree->AsIntCon(); - ssize_t cnsVal = con->IconValue(); + GenTreeIntConCommon* con = tree->AsIntConCommon(); + ssize_t cnsVal = con->IconValue(); emitAttr attr = emitActualTypeSize(targetType); // TODO-CQ: Currently we cannot do this for all handles because of @@ -2325,7 +2275,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre } instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal, - INS_FLAGS_DONT_CARE DEBUGARG(con->gtTargetHandle) DEBUGARG(con->gtFlags)); + INS_FLAGS_DONT_CARE DEBUGARG(tree->AsIntCon()->gtTargetHandle) + DEBUGARG(tree->AsIntCon()->gtFlags)); regSet.verifyRegUsed(targetReg); } break; @@ -4576,19 +4527,6 @@ void CodeGen::SetSaveFpLrWithAllCalleeSavedRegisters(bool value) { JITDUMP("Setting genSaveFpLrWithAllCalleeSavedRegisters to %s\n", dspBool(value)); genSaveFpLrWithAllCalleeSavedRegisters = value; - - if (genSaveFpLrWithAllCalleeSavedRegisters) - { - // We'll use frame type 4 or 5. Frame type 5 only occurs if there is a very large outgoing argument - // space. This is extremely rare, so under stress force using this frame type. However, frame type 5 - // isn't used if there is no outgoing argument space; this is checked elsewhere. - - if ((compiler->opts.compJitSaveFpLrWithCalleeSavedRegisters == 3) || - compiler->compStressCompile(Compiler::STRESS_GENERIC_VARN, 50)) - { - genForceFuncletFrameType5 = true; - } - } } //--------------------------------------------------------------------- @@ -10343,34 +10281,18 @@ void CodeGen::genCodeForAddEx(GenTreeOp* tree) // void CodeGen::genCodeForCond(GenTreeOp* tree) { - assert(tree->OperIs(GT_CSNEG_MI, GT_CNEG_LT)); - assert(!(tree->gtFlags & GTF_SET_FLAGS)); + assert(tree->OperIs(GT_CSNEG_MI)); + assert(!(tree->gtFlags & GTF_SET_FLAGS) && (tree->gtFlags & GTF_USE_FLAGS)); genConsumeOperands(tree); + instruction ins; + insCond cond; switch (tree->OperGet()) { case GT_CSNEG_MI: { - instruction ins = INS_csneg; - insCond cond = INS_COND_MI; - - regNumber dstReg = tree->GetRegNum(); - regNumber op1Reg = tree->gtGetOp1()->GetRegNum(); - regNumber op2Reg = tree->gtGetOp2()->GetRegNum(); - - GetEmitter()->emitIns_R_R_R_COND(ins, emitActualTypeSize(tree), dstReg, op1Reg, op2Reg, cond); - break; - } - - case GT_CNEG_LT: - { - instruction ins = INS_cneg; - insCond cond = INS_COND_LT; - - regNumber dstReg = tree->GetRegNum(); - regNumber op1Reg = tree->gtGetOp1()->GetRegNum(); - - GetEmitter()->emitIns_R_R_COND(ins, emitActualTypeSize(tree), dstReg, op1Reg, cond); + ins = INS_csneg; + cond = INS_COND_MI; break; } @@ -10378,6 +10300,11 @@ void CodeGen::genCodeForCond(GenTreeOp* tree) unreached(); } + regNumber dstReg = tree->GetRegNum(); + regNumber op1Reg = tree->gtGetOp1()->GetRegNum(); + regNumber op2Reg = tree->gtGetOp2()->GetRegNum(); + + GetEmitter()->emitIns_R_R_R_COND(ins, emitActualTypeSize(tree), dstReg, op1Reg, op2Reg, cond); genProduceReg(tree); } diff --git a/src/coreclr/jit/codegenarmarch.cpp b/src/coreclr/jit/codegenarmarch.cpp index dd4c25c5f0763..f5de40823259e 100644 --- a/src/coreclr/jit/codegenarmarch.cpp +++ b/src/coreclr/jit/codegenarmarch.cpp @@ -324,7 +324,6 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode) break; case GT_CSNEG_MI: - case GT_CNEG_LT: genCodeForCond(treeNode->AsOp()); break; #endif // TARGET_ARM64 @@ -771,7 +770,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) GenTree* source = treeNode->gtGetOp1(); - if (!source->TypeIs(TYP_STRUCT)) // a normal non-Struct argument + bool isStruct = source->TypeIs(TYP_STRUCT) || (source->OperGet() == GT_FIELD_LIST); + + if (!isStruct) // a normal non-Struct argument { if (varTypeIsSIMD(source->TypeGet())) { @@ -863,9 +864,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) { genPutArgStkFieldList(treeNode, varNumOut); } - else + else // We must have a GT_OBJ or a GT_LCL_VAR { - noway_assert(source->OperIsLocalRead() || source->OperIs(GT_OBJ)); + noway_assert(source->OperIs(GT_LCL_VAR, GT_OBJ)); var_types targetType = source->TypeGet(); noway_assert(varTypeIsStruct(targetType)); @@ -878,42 +879,96 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) #ifdef TARGET_ARM64 regNumber hiReg = treeNode->GetSingleTempReg(); #endif // TARGET_ARM64 + regNumber addrReg = REG_NA; - GenTreeLclVarCommon* srcLclNode = nullptr; - regNumber addrReg = REG_NA; - ClassLayout* layout = nullptr; + GenTreeLclVarCommon* varNode = nullptr; + GenTree* addrNode = nullptr; - // Setup "layout", "srcLclNode" and "addrReg". - if (source->OperIsLocalRead()) + if (source->OperGet() == GT_LCL_VAR) { - srcLclNode = source->AsLclVarCommon(); - layout = srcLclNode->GetLayout(compiler); - LclVarDsc* varDsc = compiler->lvaGetDesc(srcLclNode); - - // This struct must live on the stack frame. - assert(varDsc->lvOnFrame && !varDsc->lvRegister); + varNode = source->AsLclVarCommon(); } else // we must have a GT_OBJ { - layout = source->AsObj()->GetLayout(); - addrReg = genConsumeReg(source->AsObj()->Addr()); + assert(source->OperGet() == GT_OBJ); -#ifdef TARGET_ARM64 - // If addrReg equal to loReg, swap(loReg, hiReg) - // This reduces code complexity by only supporting one addrReg overwrite case - if (loReg == addrReg) + addrNode = source->AsOp()->gtOp1; + + // addrNode can either be a GT_LCL_VAR_ADDR or an address expression + // + if (addrNode->OperGet() == GT_LCL_VAR_ADDR) { - loReg = hiReg; - hiReg = addrReg; + // We have a GT_OBJ(GT_LCL_VAR_ADDR) + // + // We will treat this case the same as above + // (i.e if we just had this GT_LCL_VAR directly as the source) + // so update 'source' to point this GT_LCL_VAR_ADDR node + // and continue to the codegen for the LCL_VAR node below + // + assert(addrNode->isContained()); + varNode = addrNode->AsLclVarCommon(); + addrNode = nullptr; } + else // addrNode is used + { + // TODO-Cleanup: `Lowering::NewPutArg` marks only `LCL_VAR_ADDR` as contained nowadays, + // but we use `genConsumeAddress` as a precaution, use `genConsumeReg()` instead. + assert(!addrNode->isContained()); + // Generate code to load the address that we need into a register + genConsumeAddress(addrNode); + addrReg = addrNode->GetRegNum(); + +#ifdef TARGET_ARM64 + // If addrReg equal to loReg, swap(loReg, hiReg) + // This reduces code complexity by only supporting one addrReg overwrite case + if (loReg == addrReg) + { + loReg = hiReg; + hiReg = addrReg; + } #endif // TARGET_ARM64 + } } - unsigned srcSize = layout->GetSize(); + // Either varNode or addrNOde must have been setup above, + // the xor ensures that only one of the two is setup, not both + assert((varNode != nullptr) ^ (addrNode != nullptr)); + + ClassLayout* layout; + unsigned srcSize; + bool isHfa; + + // Setup the srcSize, isHFa, and gcPtrCount + if (source->OperGet() == GT_LCL_VAR) + { + assert(varNode != nullptr); + LclVarDsc* varDsc = compiler->lvaGetDesc(varNode); + + // This struct also must live in the stack frame + // And it can't live in a register (SIMD) + assert(varDsc->lvType == TYP_STRUCT); + assert(varDsc->lvOnFrame && !varDsc->lvRegister); + + srcSize = varDsc->lvSize(); + isHfa = varDsc->lvIsHfa(); + layout = varDsc->GetLayout(); + } + else // we must have a GT_OBJ + { + assert(source->OperGet() == GT_OBJ); + + // If the source is an OBJ node then we need to use the type information + // it provides (size and GC layout) even if the node wraps a lclvar. Due + // to struct reinterpretation (e.g. Unsafe.As) it is possible that + // the OBJ node has a different type than the lclvar. + layout = source->AsObj()->GetLayout(); + srcSize = layout->GetSize(); + isHfa = compiler->IsHfa(layout->GetClassHandle()); + } // If we have an HFA we can't have any GC pointers, // if not then the max size for the struct is 16 bytes - if (compiler->IsHfa(layout->GetClassHandle())) + if (isHfa) { noway_assert(!layout->HasGCPtr()); } @@ -926,32 +981,45 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) noway_assert(srcSize <= MAX_PASS_MULTIREG_BYTES); #endif // TARGET_ARM64 - unsigned dstSize = treeNode->GetStackByteSize(); + unsigned structSize; - // We can generate smaller code if store size is a multiple of TARGET_POINTER_SIZE. - // The dst size can be rounded up to PUTARG_STK size. The src size can be rounded up - // if it reads a local variable because reading "too much" from a local cannot fault. - // We must also be careful to check for the arm64 apple case where arguments can be - // passed without padding. - // - if ((dstSize != srcSize) && (srcLclNode != nullptr)) + unsigned dstSize = treeNode->GetStackByteSize(); + if (dstSize != srcSize) { - unsigned widenedSrcSize = roundUp(srcSize, TARGET_POINTER_SIZE); - if (widenedSrcSize <= dstSize) + // We can generate a smaller code if store size is a multiple of TARGET_POINTER_SIZE. + // The dst size can be rounded up to PUTARG_STK size. + // The src size can be rounded up if it reads a local variable slot because the local + // variable stack allocation size is rounded up to be a multiple of the TARGET_POINTER_SIZE. + // The exception is arm64 apple arguments because they can be passed without padding. + if (varNode != nullptr) { - srcSize = widenedSrcSize; + // If we have a varNode, even if it was casted using `OBJ`, we can read its original memory size. + const LclVarDsc* varDsc = compiler->lvaGetDesc(varNode); + const unsigned varStackSize = varDsc->lvSize(); + if (varStackSize >= srcSize) + { + srcSize = varStackSize; + } } } + if (dstSize == srcSize) + { + structSize = dstSize; + } + else + { + // With Unsafe object cast we can have different strange combinations: + // PutArgStk<8>(Obj<16>(LclVar<8>)) -> copy 8 bytes; + // PutArgStk<16>(Obj<16>(LclVar<8>)) -> copy 16 bytes, reading undefined memory after the local. + structSize = min(dstSize, srcSize); + } - assert(srcSize <= dstSize); - - int remainingSize = srcSize; + int remainingSize = structSize; unsigned structOffset = 0; - unsigned lclOffset = (srcLclNode != nullptr) ? srcLclNode->GetLclOffs() : 0; unsigned nextIndex = 0; #ifdef TARGET_ARM64 - // For a >= 16-byte sizes we will generate a ldp and stp instruction each loop + // For a >= 16-byte structSize we will generate a ldp and stp instruction each loop // ldp x2, x3, [x0] // stp x2, x3, [sp, #16] @@ -960,11 +1028,11 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) var_types type0 = layout->GetGCPtrType(nextIndex + 0); var_types type1 = layout->GetGCPtrType(nextIndex + 1); - if (srcLclNode != nullptr) + if (varNode != nullptr) { - // Load from our local source + // Load from our varNumImp source emit->emitIns_R_R_S_S(INS_ldp, emitTypeSize(type0), emitTypeSize(type1), loReg, hiReg, - srcLclNode->GetLclNum(), lclOffset + structOffset); + varNode->GetLclNum(), structOffset); } else { @@ -988,18 +1056,17 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) nextIndex += 2; } #else // TARGET_ARM - // For a >= 4 byte sizes we will generate a ldr and str instruction each loop + // For a >= 4 byte structSize we will generate a ldr and str instruction each loop // ldr r2, [r0] // str r2, [sp, #16] while (remainingSize >= TARGET_POINTER_SIZE) { var_types type = layout->GetGCPtrType(nextIndex); - if (srcLclNode != nullptr) + if (varNode != nullptr) { - // Load from our local source - emit->emitIns_R_S(INS_ldr, emitTypeSize(type), loReg, srcLclNode->GetLclNum(), - lclOffset + structOffset); + // Load from our varNumImp source + emit->emitIns_R_S(INS_ldr, emitTypeSize(type), loReg, varNode->GetLclNum(), structOffset); } else { @@ -1021,7 +1088,7 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) } #endif // TARGET_ARM - // For a 12-byte size we will generate two load instructions + // For a 12-byte structSize we will generate two load instructions // ldr x2, [x0] // ldr w3, [x0, #8] // str x2, [sp, #16] @@ -1062,10 +1129,10 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode) remainingSize -= moveSize; instruction loadIns = ins_Load(type); - if (srcLclNode != nullptr) + if (varNode != nullptr) { - // Load from our local source - emit->emitIns_R_S(loadIns, attr, loReg, srcLclNode->GetLclNum(), lclOffset + structOffset); + // Load from our varNumImp source + emit->emitIns_R_S(loadIns, attr, loReg, varNode->GetLclNum(), structOffset); } else { @@ -1239,8 +1306,14 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) } else // addrNode is used { + assert(addrNode != nullptr); + // TODO-Cleanup: `Lowering::NewPutArg` marks only `LCL_VAR_ADDR` as contained nowadays, + // but we use `genConsumeAddress` as a precaution, use `genConsumeReg()` instead. + assert(!addrNode->isContained()); + // Generate code to load the address that we need into a register - addrReg = genConsumeReg(addrNode); + genConsumeAddress(addrNode); + addrReg = addrNode->GetRegNum(); // If addrReg equal to baseReg, we use the last target register as alternative baseReg. // Because the candidate mask for the internal baseReg does not include any of the target register, @@ -1254,40 +1327,21 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) ClassLayout* layout = source->AsObj()->GetLayout(); // Put on stack first - unsigned structOffset = treeNode->gtNumRegs * TARGET_POINTER_SIZE; - unsigned remainingSize = layout->GetSize() - structOffset; + unsigned nextIndex = treeNode->gtNumRegs; + unsigned structOffset = nextIndex * TARGET_POINTER_SIZE; + int remainingSize = treeNode->GetStackByteSize(); unsigned argOffsetOut = treeNode->getArgOffset(); - assert((remainingSize > 0) && (roundUp(remainingSize, TARGET_POINTER_SIZE) == treeNode->GetStackByteSize())); + // remainingSize is always multiple of TARGET_POINTER_SIZE + assert(remainingSize % TARGET_POINTER_SIZE == 0); while (remainingSize > 0) { - var_types type; - if (remainingSize >= TARGET_POINTER_SIZE) - { - type = layout->GetGCPtrType(structOffset / TARGET_POINTER_SIZE); - } - else if (remainingSize >= 4) - { - type = TYP_INT; - } - else if (remainingSize >= 2) - { - type = TYP_USHORT; - } - else - { - assert(remainingSize == 1); - type = TYP_UBYTE; - } - - emitAttr attr = emitActualTypeSize(type); - unsigned moveSize = genTypeSize(type); + var_types type = layout->GetGCPtrType(nextIndex); - instruction loadIns = ins_Load(type); if (varNode != nullptr) { - // Load from our local source - emit->emitIns_R_S(loadIns, attr, baseReg, srcVarNum, structOffset); + // Load from our varNumImp source + emit->emitIns_R_S(INS_ldr, emitTypeSize(type), baseReg, srcVarNum, structOffset); } else { @@ -1295,16 +1349,16 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) assert(baseReg != addrReg); // Load from our address expression source - emit->emitIns_R_R_I(loadIns, attr, baseReg, addrReg, structOffset); + emit->emitIns_R_R_I(INS_ldr, emitTypeSize(type), baseReg, addrReg, structOffset); } - // Emit the instruction to store the register into the outgoing argument area - emit->emitIns_S_R(ins_Store(type), attr, baseReg, varNumOut, argOffsetOut); - argOffsetOut += moveSize; - assert(argOffsetOut <= argOffsetMax); - - remainingSize -= moveSize; - structOffset += moveSize; + // Emit str instruction to store the register into the outgoing argument area + emit->emitIns_S_R(INS_str, emitTypeSize(type), baseReg, varNumOut, argOffsetOut); + argOffsetOut += TARGET_POINTER_SIZE; // We stored 4-bytes of the struct + assert(argOffsetOut <= argOffsetMax); // We can't write beyond the outgoing arg area + remainingSize -= TARGET_POINTER_SIZE; // We loaded 4-bytes of the struct + structOffset += TARGET_POINTER_SIZE; + nextIndex += 1; } // We set up the registers in order, so that we assign the last target register `baseReg` is no longer in use, @@ -1317,7 +1371,7 @@ void CodeGen::genPutArgSplit(GenTreePutArgSplit* treeNode) if (varNode != nullptr) { - // Load from our local source + // Load from our varNumImp source emit->emitIns_R_S(INS_ldr, emitTypeSize(type), targetReg, srcVarNum, structOffset); } else @@ -3875,9 +3929,14 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d case GenIntCastDesc::CHECK_INT_RANGE: { - // Emit "if ((long)(int)x != x) goto OVERFLOW" - GetEmitter()->emitIns_R_R(INS_cmp, EA_8BYTE, reg, reg, INS_OPTS_SXTW); - genJumpToThrowHlpBlk(EJ_ne, SCK_OVERFLOW); + const regNumber tempReg = cast->GetSingleTempReg(); + assert(tempReg != reg); + instGen_Set_Reg_To_Imm(EA_8BYTE, tempReg, INT32_MAX); + GetEmitter()->emitIns_R_R(INS_cmp, EA_8BYTE, reg, tempReg); + genJumpToThrowHlpBlk(EJ_gt, SCK_OVERFLOW); + instGen_Set_Reg_To_Imm(EA_8BYTE, tempReg, INT32_MIN); + GetEmitter()->emitIns_R_R(INS_cmp, EA_8BYTE, reg, tempReg); + genJumpToThrowHlpBlk(EJ_lt, SCK_OVERFLOW); } break; #endif @@ -4426,16 +4485,6 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) } else { -#ifdef TARGET_ARM64 - // Handle LEA with "contained" BFIZ - if (index->isContained() && index->OperIs(GT_BFIZ)) - { - assert(scale == 0); - scale = (DWORD)index->gtGetOp2()->AsIntConCommon()->IconValue(); - index = index->gtGetOp1()->gtGetOp1(); - } -#endif - // Then compute target reg from [base + index*scale] genScaledAdd(size, lea->GetRegNum(), memBase->GetRegNum(), index->GetRegNum(), scale); } @@ -4657,7 +4706,7 @@ void CodeGen::genPushCalleeSavedRegisters() // |-----------------------| // |Callee saved registers | // not including FP/LR; multiple of 8 bytes // |-----------------------| - // | MonitorAcquired | // 8 bytes; for synchronized methods + // | MonitorAcquired | // |-----------------------| // | PSP slot | // 8 bytes (omitted in NativeAOT ABI) // |-----------------------| @@ -4690,7 +4739,7 @@ void CodeGen::genPushCalleeSavedRegisters() // |-----------------------| // |Callee saved registers | // not including FP/LR; multiple of 8 bytes // |-----------------------| - // | MonitorAcquired | // 8 bytes; for synchronized methods + // | MonitorAcquired | // |-----------------------| // | PSP slot | // 8 bytes (omitted in NativeAOT ABI) // |-----------------------| diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index d158a56211698..ed16b9a9fa498 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -137,7 +137,6 @@ CodeGen::CodeGen(Compiler* theCompiler) : CodeGenInterface(theCompiler) #ifdef TARGET_ARM64 genSaveFpLrWithAllCalleeSavedRegisters = false; - genForceFuncletFrameType5 = false; #endif // TARGET_ARM64 } @@ -6582,6 +6581,35 @@ bool Compiler::IsHfa(CORINFO_CLASS_HANDLE hClass) return varTypeIsValidHfaType(GetHfaType(hClass)); } +bool Compiler::IsHfa(GenTree* tree) +{ + if (GlobalJitOptions::compFeatureHfa) + { + return IsHfa(gtGetStructHandleIfPresent(tree)); + } + else + { + return false; + } +} + +var_types Compiler::GetHfaType(GenTree* tree) +{ + if (GlobalJitOptions::compFeatureHfa) + { + return GetHfaType(gtGetStructHandleIfPresent(tree)); + } + else + { + return TYP_UNDEF; + } +} + +unsigned Compiler::GetHfaCount(GenTree* tree) +{ + return GetHfaCount(gtGetStructHandle(tree)); +} + var_types Compiler::GetHfaType(CORINFO_CLASS_HANDLE hClass) { if (GlobalJitOptions::compFeatureHfa) diff --git a/src/coreclr/jit/codegenlinear.cpp b/src/coreclr/jit/codegenlinear.cpp index b9026bfedd6f4..6a44f1db324de 100644 --- a/src/coreclr/jit/codegenlinear.cpp +++ b/src/coreclr/jit/codegenlinear.cpp @@ -753,27 +753,24 @@ void CodeGen::genCodeForBBlist() break; case BBJ_ALWAYS: -#ifdef TARGET_XARCH - { - // If a block was selected to place an alignment instruction because it ended - // with a jump, do not remove jumps from such blocks. - // Do not remove a jump between hot and cold regions. - bool isRemovableJmpCandidate = - !block->hasAlign() && !compiler->fgInDifferentRegions(block, block->bbJumpDest); - + inst_JMP(EJ_jmp, block->bbJumpDest #ifdef TARGET_AMD64 - // AMD64 requires an instruction after a call instruction for unwinding - // inside an EH region so if the last instruction generated was a call instruction - // do not allow this jump to be marked for possible later removal. - isRemovableJmpCandidate = isRemovableJmpCandidate && !GetEmitter()->emitIsLastInsCall(); -#endif // TARGET_AMD64 - - inst_JMP(EJ_jmp, block->bbJumpDest, isRemovableJmpCandidate); - } + // AMD64 requires an instruction after a call instruction for unwinding + // inside an EH region so if the last instruction generated was a call instruction + // do not allow this jump to be marked for possible later removal. + // + // If a block was selected to place an alignment instruction because it ended + // with a jump, do not remove jumps from such blocks. + , + /* isRemovableJmpCandidate */ !GetEmitter()->emitIsLastInsCall() && !block->hasAlign() #else - inst_JMP(EJ_jmp, block->bbJumpDest); -#endif // TARGET_XARCH +#ifdef TARGET_XARCH + , + /* isRemovableJmpCandidate */ !block->hasAlign() +#endif +#endif + ); FALLTHROUGH; case BBJ_COND: @@ -1765,21 +1762,21 @@ void CodeGen::genConsumePutStructArgStk(GenTreePutArgStk* putArgNode, regNumber sizeReg) { // The putArgNode children are always contained. We should not consume any registers. - assert(putArgNode->Data()->isContained()); + assert(putArgNode->gtGetOp1()->isContained()); - // Get the source. - GenTree* src = putArgNode->Data(); - regNumber srcAddrReg = REG_NA; + // Get the source address. + GenTree* src = putArgNode->gtGetOp1(); assert(varTypeIsStruct(src)); - assert(src->OperIs(GT_OBJ) || src->OperIsLocalRead() || (src->OperIs(GT_IND) && varTypeIsSIMD(src))); + assert((src->gtOper == GT_OBJ) || ((src->gtOper == GT_IND && varTypeIsSIMD(src)))); + GenTree* srcAddr = src->gtGetOp1(); assert(dstReg != REG_NA); assert(srcReg != REG_NA); - // Consume the register for the source address if needed. - if (src->OperIsIndir()) + // Consume the registers only if they are not contained or set to REG_NA. + if (srcAddr->GetRegNum() != REG_NA) { - srcAddrReg = genConsumeReg(src->AsIndir()->Addr()); + genConsumeReg(srcAddr); } // If the op1 is already in the dstReg - nothing to do. @@ -1801,17 +1798,22 @@ void CodeGen::genConsumePutStructArgStk(GenTreePutArgStk* putArgNode, } #endif // !TARGET_X86 - if (srcAddrReg != REG_NA) + if (srcAddr->OperIsLocalAddr()) { - // Source is not known to be on the stack. Use EA_BYREF. - GetEmitter()->emitIns_Mov(INS_mov, EA_BYREF, srcReg, srcAddrReg, /* canSkip */ true); + // The OperLocalAddr is always contained. + assert(srcAddr->isContained()); + const GenTreeLclVarCommon* lclNode = srcAddr->AsLclVarCommon(); + + // Generate LEA instruction to load the LclVar address in RSI. + // Source is known to be on the stack. Use EA_PTRSIZE. + unsigned int offset = lclNode->GetLclOffs(); + GetEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, srcReg, lclNode->GetLclNum(), offset); } else { - // Generate LEA instruction to load the LclVar address in RSI. - // Source is known to be on the stack. Use EA_PTRSIZE. - GetEmitter()->emitIns_R_S(INS_lea, EA_PTRSIZE, srcReg, src->AsLclVarCommon()->GetLclNum(), - src->AsLclVarCommon()->GetLclOffs()); + assert(srcAddr->GetRegNum() != REG_NA); + // Source is not known to be on the stack. Use EA_BYREF. + GetEmitter()->emitIns_Mov(INS_mov, EA_BYREF, srcReg, srcAddr->GetRegNum(), /* canSkip */ true); } if (sizeReg != REG_NA) diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 7f85403db4017..67d64db8c6a82 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -1655,18 +1655,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -//------------------------------------------------------------------------ -// inst_JMP: Generate a jump instruction. -// -void CodeGen::inst_JMP(emitJumpKind jmp, BasicBlock* tgtBlock) -{ -#if !FEATURE_FIXED_OUT_ARGS - assert((tgtBlock->bbTgtStkDepth * sizeof(int) == genStackLevel) || isFramePointerUsed()); -#endif // !FEATURE_FIXED_OUT_ARGS - - GetEmitter()->emitIns_J(emitter::emitJumpKindToIns(jmp), tgtBlock); -} - BasicBlock* CodeGen::genCallFinally(BasicBlock* block) { // Generate a call to the finally, like this: diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index ca050dcf49ff9..039d4c1118522 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -442,7 +442,7 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, } else { - GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm DEBUGARG(targetHandle) DEBUGARG(gtFlags)); + GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm DEBUGARG(gtFlags)); } } regSet.verifyRegUsed(reg); @@ -462,8 +462,8 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre { // relocatable values tend to come down as a CNS_INT of native int type // so the line between these two opcodes is kind of blurry - GenTreeIntCon* con = tree->AsIntCon(); - ssize_t cnsVal = con->IconValue(); + GenTreeIntConCommon* con = tree->AsIntConCommon(); + ssize_t cnsVal = con->IconValue(); emitAttr attr = emitActualTypeSize(targetType); // Currently this cannot be done for all handles due to @@ -482,8 +482,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre attr = EA_SET_FLG(attr, EA_BYREF_FLG); } - instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal, - INS_FLAGS_DONT_CARE DEBUGARG(con->gtTargetHandle) DEBUGARG(con->gtFlags)); + instGen_Set_Reg_To_Imm(attr, targetReg, cnsVal, INS_FLAGS_DONT_CARE DEBUGARG(0) DEBUGARG(tree->gtFlags)); regSet.verifyRegUsed(targetReg); } break; @@ -517,28 +516,22 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre if (vecCon->IsAllBitsSet()) { - if ((attr != EA_32BYTE) || compiler->compOpportunisticallyDependsOn(InstructionSet_AVX2)) - { #if defined(FEATURE_SIMD) - emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_pcmpeqd, attr, targetReg, targetReg, targetReg); #else - emit->emitIns_R_R(INS_pcmpeqd, attr, targetReg, targetReg); + emit->emitIns_R_R(INS_pcmpeqd, attr, targetReg, targetReg); #endif // FEATURE_SIMD - break; - } + break; } if (vecCon->IsZero()) { - if ((attr != EA_32BYTE) || compiler->compOpportunisticallyDependsOn(InstructionSet_AVX)) - { #if defined(FEATURE_SIMD) - emit->emitIns_SIMD_R_R_R(INS_xorps, attr, targetReg, targetReg, targetReg); + emit->emitIns_SIMD_R_R_R(INS_xorps, attr, targetReg, targetReg, targetReg); #else - emit->emitIns_R_R(INS_xorps, attr, targetReg, targetReg); + emit->emitIns_R_R(INS_xorps, attr, targetReg, targetReg); #endif // FEATURE_SIMD - break; - } + break; } switch (tree->TypeGet()) @@ -3059,19 +3052,21 @@ void CodeGen::genCodeForInitBlkHelper(GenTreeBlk* initBlkNode) #ifdef FEATURE_PUT_STRUCT_ARG_STK // Generate code for a load from some address + offset -// base: tree node which can be either a local or an indir -// offset: distance from the "base" location from which to load -// -void CodeGen::genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* base, unsigned offset) +// baseNode: tree node which can be either a local address or arbitrary node +// offset: distance from the baseNode from which to load +void CodeGen::genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* baseNode, unsigned offset) { - if (base->OperIsLocalRead()) + emitter* emit = GetEmitter(); + + if (baseNode->OperIsLocalAddr()) { - GetEmitter()->emitIns_R_S(ins, size, dst, base->AsLclVarCommon()->GetLclNum(), - offset + base->AsLclVarCommon()->GetLclOffs()); + const GenTreeLclVarCommon* lclVar = baseNode->AsLclVarCommon(); + offset += lclVar->GetLclOffs(); + emit->emitIns_R_S(ins, size, dst, lclVar->GetLclNum(), offset); } else { - GetEmitter()->emitIns_R_AR(ins, size, dst, base->AsIndir()->Addr()->GetRegNum(), offset); + emit->emitIns_R_AR(ins, size, dst, baseNode->GetRegNum(), offset); } } #endif // FEATURE_PUT_STRUCT_ARG_STK @@ -3342,7 +3337,7 @@ void CodeGen::genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode) // Arguments: // size - The size of bytes remaining to be moved // longTmpReg - The tmp register to be used for the long value -// src - The source struct node (LCL/OBJ) +// srcAddr - The address of the source struct // offset - The current offset being copied // // Return Value: @@ -3354,7 +3349,7 @@ void CodeGen::genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode) // On x86, longTmpReg must be an xmm reg; on x64 it must be an integer register. // This is checked by genStoreRegToStackArg. // -unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* src, unsigned offset) +unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* srcAddr, unsigned offset) { #ifdef TARGET_X86 instruction longMovIns = INS_movq; @@ -3363,7 +3358,7 @@ unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* #endif // !TARGET_X86 if ((size & 8) != 0) { - genCodeForLoadOffset(longMovIns, EA_8BYTE, longTmpReg, src, offset); + genCodeForLoadOffset(longMovIns, EA_8BYTE, longTmpReg, srcAddr, offset); genStoreRegToStackArg(TYP_LONG, longTmpReg, offset); return 8; } @@ -3376,7 +3371,7 @@ unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* // Arguments: // size - The size of bytes remaining to be moved // intTmpReg - The tmp register to be used for the long value -// src - The source struct node (LCL/OBJ) +// srcAddr - The address of the source struct // offset - The current offset being copied // // Return Value: @@ -3388,11 +3383,11 @@ unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* // intTmpReg must be an integer register. // This is checked by genStoreRegToStackArg. // -unsigned CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* src, unsigned offset) +unsigned CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset) { if ((size & 4) != 0) { - genCodeForLoadOffset(INS_mov, EA_4BYTE, intTmpReg, src, offset); + genCodeForLoadOffset(INS_mov, EA_4BYTE, intTmpReg, srcAddr, offset); genStoreRegToStackArg(TYP_INT, intTmpReg, offset); return 4; } @@ -3405,7 +3400,7 @@ unsigned CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* // Arguments: // size - The size of bytes remaining to be moved // intTmpReg - The tmp register to be used for the long value -// src - The source struct node (LCL/OBJ) +// srcAddr - The address of the source struct // offset - The current offset being copied // // Return Value: @@ -3417,11 +3412,11 @@ unsigned CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* // intTmpReg must be an integer register. // This is checked by genStoreRegToStackArg. // -unsigned CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* src, unsigned offset) +unsigned CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset) { if ((size & 2) != 0) { - genCodeForLoadOffset(INS_mov, EA_2BYTE, intTmpReg, src, offset); + genCodeForLoadOffset(INS_mov, EA_2BYTE, intTmpReg, srcAddr, offset); genStoreRegToStackArg(TYP_SHORT, intTmpReg, offset); return 2; } @@ -3434,7 +3429,7 @@ unsigned CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* // Arguments: // size - The size of bytes remaining to be moved // intTmpReg - The tmp register to be used for the long value -// src - The source struct node (LCL/OBJ) +// srcAddr - The address of the source struct // offset - The current offset being copied // // Return Value: @@ -3446,11 +3441,11 @@ unsigned CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* // intTmpReg must be an integer register. // This is checked by genStoreRegToStackArg. // -unsigned CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* src, unsigned offset) +unsigned CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset) { if ((size & 1) != 0) { - genCodeForLoadOffset(INS_mov, EA_1BYTE, intTmpReg, src, offset); + genCodeForLoadOffset(INS_mov, EA_1BYTE, intTmpReg, srcAddr, offset); genStoreRegToStackArg(TYP_BYTE, intTmpReg, offset); return 1; } @@ -3474,36 +3469,37 @@ unsigned CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* // void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) { - GenTree* src = putArgNode->Data(); - // We will never call this method for SIMD types, which are stored directly in genPutStructArgStk(). - assert(src->isContained() && src->TypeIs(TYP_STRUCT) && (src->OperIs(GT_OBJ) || src->OperIsLocalRead())); - + GenTree* src = putArgNode->AsOp()->gtOp1; + // We will never call this method for SIMD types, which are stored directly + // in genPutStructArgStk(). + assert(src->isContained() && src->OperIs(GT_OBJ) && src->TypeIs(TYP_STRUCT)); + assert(!src->AsObj()->GetLayout()->HasGCPtr()); #ifdef TARGET_X86 assert(!m_pushStkArg); #endif - if (src->OperIs(GT_OBJ)) + unsigned size = putArgNode->GetStackByteSize(); +#ifdef TARGET_X86 + assert((XMM_REGSIZE_BYTES <= size) && (size <= CPBLK_UNROLL_LIMIT)); +#else // !TARGET_X86 + assert(size <= CPBLK_UNROLL_LIMIT); +#endif // !TARGET_X86 + + if (src->AsOp()->gtOp1->isUsedFromReg()) { - genConsumeReg(src->AsObj()->Addr()); + genConsumeReg(src->AsOp()->gtOp1); } - unsigned loadSize = putArgNode->GetArgLoadSize(); - assert(!src->GetLayout(compiler)->HasGCPtr() && (loadSize <= CPBLK_UNROLL_LIMIT)); - unsigned offset = 0; regNumber xmmTmpReg = REG_NA; regNumber intTmpReg = REG_NA; regNumber longTmpReg = REG_NA; -#ifdef TARGET_X86 - if (loadSize >= 8) -#else - if (loadSize >= XMM_REGSIZE_BYTES) -#endif + if (size >= XMM_REGSIZE_BYTES) { xmmTmpReg = putArgNode->GetSingleTempReg(RBM_ALLFLOAT); } - if ((loadSize % XMM_REGSIZE_BYTES) != 0) + if ((size % XMM_REGSIZE_BYTES) != 0) { intTmpReg = putArgNode->GetSingleTempReg(RBM_ALLINT); } @@ -3515,7 +3511,7 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) #endif // Let's use SSE2 to be able to do 16 byte at a time with loads and stores. - size_t slots = loadSize / XMM_REGSIZE_BYTES; + size_t slots = size / XMM_REGSIZE_BYTES; while (slots-- > 0) { // TODO: In the below code the load and store instructions are for 16 bytes, but the @@ -3523,7 +3519,7 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) // this probably needs to be changed. // Load - genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmTmpReg, src, offset); + genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmTmpReg, src->gtGetOp1(), offset); // Store genStoreRegToStackArg(TYP_STRUCT, xmmTmpReg, offset); @@ -3531,13 +3527,13 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) } // Fill the remainder (15 bytes or less) if there's one. - if ((loadSize % XMM_REGSIZE_BYTES) != 0) + if ((size % XMM_REGSIZE_BYTES) != 0) { - offset += genMove8IfNeeded(loadSize, longTmpReg, src, offset); - offset += genMove4IfNeeded(loadSize, intTmpReg, src, offset); - offset += genMove2IfNeeded(loadSize, intTmpReg, src, offset); - offset += genMove1IfNeeded(loadSize, intTmpReg, src, offset); - assert(offset == loadSize); + offset += genMove8IfNeeded(size, longTmpReg, src->AsOp()->gtOp1, offset); + offset += genMove4IfNeeded(size, intTmpReg, src->AsOp()->gtOp1, offset); + offset += genMove2IfNeeded(size, intTmpReg, src->AsOp()->gtOp1, offset); + offset += genMove1IfNeeded(size, intTmpReg, src->AsOp()->gtOp1, offset); + assert(offset == size); } } @@ -3553,7 +3549,8 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode) void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode) { GenTree* src = putArgNode->gtGetOp1(); - assert(src->TypeIs(TYP_STRUCT) && !src->GetLayout(compiler)->HasGCPtr()); + assert(src->TypeGet() == TYP_STRUCT); + assert(!src->AsObj()->GetLayout()->HasGCPtr()); // Make sure we got the arguments of the cpblk operation in the right registers, and that // 'src' is contained as expected. @@ -3572,9 +3569,8 @@ void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode) // putArgNode - the PutArgStk tree. // // Notes: -// Used (only) on x86 for: +// Used only on x86, in two cases: // - Structs 4, 8, or 12 bytes in size (less than XMM_REGSIZE_BYTES, multiple of TARGET_POINTER_SIZE). -// - Local structs less than 16 bytes in size (it is ok to load "too much" from our stack frame). // - Structs that contain GC pointers - they are guaranteed to be sized correctly by the VM. // void CodeGen::genStructPutArgPush(GenTreePutArgStk* putArgNode) @@ -3587,37 +3583,42 @@ void CodeGen::genStructPutArgPush(GenTreePutArgStk* putArgNode) // future. assert(m_pushStkArg); - GenTree* src = putArgNode->Data(); - regNumber srcAddrReg = REG_NA; - unsigned srcLclNum = BAD_VAR_NUM; - unsigned srcLclOffs = BAD_LCL_OFFSET; - if (src->OperIsLocalRead()) + GenTree* src = putArgNode->Data(); + GenTree* srcAddr = putArgNode->Data()->AsObj()->Addr(); + + regNumber srcAddrReg = srcAddr->GetRegNum(); + const bool srcAddrInReg = srcAddrReg != REG_NA; + + unsigned srcLclNum = 0; + unsigned srcLclOffset = 0; + if (srcAddrInReg) { - assert(src->isContained()); - srcLclNum = src->AsLclVarCommon()->GetLclNum(); - srcLclOffs = src->AsLclVarCommon()->GetLclOffs(); + srcAddrReg = genConsumeReg(srcAddr); } else { - srcAddrReg = genConsumeReg(src->AsObj()->Addr()); + assert(srcAddr->OperIsLocalAddr()); + + srcLclNum = srcAddr->AsLclVarCommon()->GetLclNum(); + srcLclOffset = srcAddr->AsLclVarCommon()->GetLclOffs(); } - ClassLayout* layout = src->GetLayout(compiler); - const unsigned loadSize = putArgNode->GetArgLoadSize(); - assert(((loadSize < XMM_REGSIZE_BYTES) || layout->HasGCPtr()) && ((loadSize % TARGET_POINTER_SIZE) == 0)); - const unsigned numSlots = loadSize / TARGET_POINTER_SIZE; + ClassLayout* layout = src->AsObj()->GetLayout(); + const unsigned byteSize = putArgNode->GetStackByteSize(); + assert((byteSize % TARGET_POINTER_SIZE == 0) && ((byteSize < XMM_REGSIZE_BYTES) || layout->HasGCPtr())); + const unsigned numSlots = byteSize / TARGET_POINTER_SIZE; for (int i = numSlots - 1; i >= 0; --i) { emitAttr slotAttr = emitTypeSize(layout->GetGCPtrType(i)); const unsigned byteOffset = i * TARGET_POINTER_SIZE; - if (srcAddrReg != REG_NA) + if (srcAddrInReg) { GetEmitter()->emitIns_AR_R(INS_push, slotAttr, REG_NA, srcAddrReg, byteOffset); } else { - GetEmitter()->emitIns_S(INS_push, slotAttr, srcLclNum, srcLclOffs + byteOffset); + GetEmitter()->emitIns_S(INS_push, slotAttr, srcLclNum, srcLclOffset + byteOffset); } AddStackLevel(TARGET_POINTER_SIZE); @@ -3642,18 +3643,19 @@ void CodeGen::genStructPutArgPartialRepMovs(GenTreePutArgStk* putArgNode) // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing"). genConsumePutStructArgStk(putArgNode, REG_RDI, REG_RSI, REG_NA); - GenTree* src = putArgNode->Data(); - ClassLayout* layout = src->GetLayout(compiler); - const emitAttr srcAddrAttr = src->OperIsLocalRead() ? EA_PTRSIZE : EA_BYREF; + GenTreeObj* src = putArgNode->gtGetOp1()->AsObj(); + ClassLayout* layout = src->GetLayout(); + const bool srcIsLocal = src->Addr()->OperIsLocalAddr(); + const emitAttr srcAddrAttr = srcIsLocal ? EA_PTRSIZE : EA_BYREF; #if DEBUG unsigned numGCSlotsCopied = 0; #endif // DEBUG assert(layout->HasGCPtr()); - const unsigned argSize = putArgNode->GetStackByteSize(); - assert(argSize % TARGET_POINTER_SIZE == 0); - const unsigned numSlots = argSize / TARGET_POINTER_SIZE; + const unsigned byteSize = putArgNode->GetStackByteSize(); + assert(byteSize % TARGET_POINTER_SIZE == 0); + const unsigned numSlots = byteSize / TARGET_POINTER_SIZE; // No need to disable GC the way COPYOBJ does. Here the refs are copied in atomic operations always. for (unsigned i = 0; i < numSlots;) @@ -4761,8 +4763,7 @@ void CodeGen::genCodeForLclFld(GenTreeLclFld* tree) unsigned varNum = tree->GetLclNum(); assert(varNum < compiler->lvaCount); - instruction loadIns = tree->DontExtend() ? INS_mov : ins_Load(targetType); - GetEmitter()->emitIns_R_S(loadIns, size, targetReg, varNum, offs); + GetEmitter()->emitIns_R_S(ins_Load(targetType), size, targetReg, varNum, offs); genProduceReg(tree); } @@ -5113,7 +5114,16 @@ void CodeGen::genCodeForIndir(GenTreeIndir* tree) else { genConsumeAddress(addr); - instruction loadIns = tree->DontExtend() ? INS_mov : ins_Load(targetType); + instruction loadIns = ins_Load(targetType); + if (tree->DontExtend()) + { + assert(varTypeIsSmall(tree)); + // The user of this IND does not need + // the upper bits to be set, so we don't need to use longer + // INS_movzx/INS_movsx and can use INS_mov instead. + // It usually happens when the real type is a small struct. + loadIns = INS_mov; + } emit->emitInsLoadInd(loadIns, emitTypeSize(tree), tree->GetRegNum(), tree); } @@ -5514,17 +5524,23 @@ void CodeGen::genCall(GenTreeCall* call) GenTree* argNode = arg.GetEarlyNode(); if (argNode->OperIs(GT_PUTARG_STK) && (arg.GetLateNode() == nullptr)) { - GenTree* source = argNode->AsPutArgStk()->gtGetOp1(); - unsigned argSize = argNode->AsPutArgStk()->GetStackByteSize(); - stackArgBytes += argSize; - + GenTree* source = argNode->AsPutArgStk()->gtGetOp1(); + unsigned size = argNode->AsPutArgStk()->GetStackByteSize(); + stackArgBytes += size; #ifdef DEBUG - assert(argSize == arg.AbiInfo.ByteSize); + assert(size == arg.AbiInfo.ByteSize); #ifdef FEATURE_PUT_STRUCT_ARG_STK - if (source->TypeIs(TYP_STRUCT) && !source->OperIs(GT_FIELD_LIST)) + if (!source->OperIs(GT_FIELD_LIST) && (source->TypeGet() == TYP_STRUCT)) { - unsigned loadSize = source->GetLayout(compiler)->GetSize(); - assert(argSize == roundUp(loadSize, TARGET_POINTER_SIZE)); + GenTreeObj* obj = source->AsObj(); + unsigned argBytes = roundUp(obj->GetLayout()->GetSize(), TARGET_POINTER_SIZE); +#ifdef TARGET_X86 + // If we have an OBJ, we must have created a copy if the original arg was not a + // local and was not a multiple of TARGET_POINTER_SIZE. + // Note that on x64/ux this will be handled by unrolling in genStructPutArgUnroll. + assert((argBytes == obj->GetLayout()->GetSize()) || obj->Addr()->IsLocalAddrExpr()); +#endif // TARGET_X86 + assert(arg.AbiInfo.ByteSize == argBytes); } #endif // FEATURE_PUT_STRUCT_ARG_STK #endif // DEBUG @@ -6730,14 +6746,11 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d break; case GenIntCastDesc::CHECK_INT_RANGE: - { - // Emit "if ((long)(int)x != x) goto OVERFLOW" - const regNumber regTmp = cast->GetSingleTempReg(); - GetEmitter()->emitIns_Mov(INS_movsxd, EA_8BYTE, regTmp, reg, true); - GetEmitter()->emitIns_R_R(INS_cmp, EA_8BYTE, reg, regTmp); - genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW); - } - break; + GetEmitter()->emitIns_R_I(INS_cmp, EA_8BYTE, reg, INT32_MAX); + genJumpToThrowHlpBlk(EJ_jg, SCK_OVERFLOW); + GetEmitter()->emitIns_R_I(INS_cmp, EA_8BYTE, reg, INT32_MIN); + genJumpToThrowHlpBlk(EJ_jl, SCK_OVERFLOW); + break; #endif default: @@ -7783,11 +7796,11 @@ bool CodeGen::genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk) { case GenTreePutArgStk::Kind::RepInstr: case GenTreePutArgStk::Kind::Unroll: - assert(!source->GetLayout(compiler)->HasGCPtr()); + assert(!source->AsObj()->GetLayout()->HasGCPtr()); break; case GenTreePutArgStk::Kind::Push: - assert(source->OperIs(GT_FIELD_LIST) || source->GetLayout(compiler)->HasGCPtr() || + assert(source->OperIs(GT_FIELD_LIST) || source->AsObj()->GetLayout()->HasGCPtr() || (argSize < XMM_REGSIZE_BYTES)); break; @@ -8301,11 +8314,14 @@ void CodeGen::genPutStructArgStk(GenTreePutArgStk* putArgStk) assert(targetType == TYP_STRUCT); + ClassLayout* layout = source->AsObj()->GetLayout(); + switch (putArgStk->gtPutArgStkKind) { case GenTreePutArgStk::Kind::RepInstr: genStructPutArgRepMovs(putArgStk); break; + #ifndef TARGET_X86 case GenTreePutArgStk::Kind::PartialRepInstr: genStructPutArgPartialRepMovs(putArgStk); diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 460412d84597e..2201c3a7d1e8d 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -3199,10 +3199,10 @@ void Compiler::compInitOptions(JitFlags* jitFlags) opts.compProcedureSplitting = jitFlags->IsSet(JitFlags::JIT_FLAG_PROCSPLIT) || enableFakeSplitting; -#ifdef TARGET_LOONGARCH64 - // Hot/cold splitting is not being tested on LoongArch64. +#ifdef TARGET_ARM64 + // TODO-ARM64-NYI: enable hot/cold splitting opts.compProcedureSplitting = false; -#endif // TARGET_LOONGARCH64 +#endif // TARGET_ARM64 #ifdef DEBUG opts.compProcedureSplittingEH = opts.compProcedureSplitting; @@ -5199,41 +5199,25 @@ void Compiler::placeLoopAlignInstructions() { // Loop alignment is disabled for cold blocks assert((block->bbFlags & BBF_COLD) == 0); - BasicBlock* const loopTop = block->bbNext; // If jmp was not found, then block before the loop start is where align instruction will be added. - // if (bbHavingAlign == nullptr) { - // In some odd cases we may see blocks within the loop before we see the - // top block of the loop. Just bail on aligning such loops. - // - if ((block->bbNatLoopNum != BasicBlock::NOT_IN_LOOP) && (block->bbNatLoopNum == loopTop->bbNatLoopNum)) - { - loopTop->unmarkLoopAlign(this DEBUG_ARG("loop block appears before top of loop")); - } - else - { - bbHavingAlign = block; - JITDUMP("Marking " FMT_BB " before the loop with BBF_HAS_ALIGN for loop at " FMT_BB "\n", - block->bbNum, loopTop->bbNum); - } + bbHavingAlign = block; + JITDUMP("Marking " FMT_BB " before the loop with BBF_HAS_ALIGN for loop at " FMT_BB "\n", block->bbNum, + block->bbNext->bbNum); } else { JITDUMP("Marking " FMT_BB " that ends with unconditional jump with BBF_HAS_ALIGN for loop at " FMT_BB "\n", - bbHavingAlign->bbNum, loopTop->bbNum); - } - - if (bbHavingAlign != nullptr) - { - bbHavingAlign->bbFlags |= BBF_HAS_ALIGN; + bbHavingAlign->bbNum, block->bbNext->bbNum); } + bbHavingAlign->bbFlags |= BBF_HAS_ALIGN; minBlockSoFar = BB_MAX_WEIGHT; bbHavingAlign = nullptr; - currentAlignedLoopNum = loopTop->bbNatLoopNum; + currentAlignedLoopNum = block->bbNext->bbNatLoopNum; if (--loopsToProcess == 0) { @@ -6400,10 +6384,10 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, compHndBBtabCount = 0; compHndBBtabAllocCount = 0; - info.compNativeCodeSize = 0; - info.compTotalHotCodeSize = 0; - info.compTotalColdCodeSize = 0; - info.compHandleHistogramProbeCount = 0; + info.compNativeCodeSize = 0; + info.compTotalHotCodeSize = 0; + info.compTotalColdCodeSize = 0; + info.compClassProbeCount = 0; compHasBackwardJump = false; compHasBackwardJumpInHandler = false; @@ -6579,7 +6563,7 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, { // This looks like a viable inline candidate. Since // we're not actually inlining, don't report anything. - prejitResult.SetSuccessResult(INLINE_PREJIT_SUCCESS); + prejitResult.SetReported(); } } else diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index b5bfdf926f212..b4c7eb375b4d2 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -477,9 +477,9 @@ class LclVarDsc unsigned char lvIsTemp : 1; // Short-lifetime compiler temp -#if FEATURE_IMPLICIT_BYREFS +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) unsigned char lvIsImplicitByRef : 1; // Set if the argument is an implicit byref. -#endif // FEATURE_IMPLICIT_BYREFS +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) #if defined(TARGET_LOONGARCH64) unsigned char lvIs4Field1 : 1; // Set if the 1st field is int or float within struct for LA-ABI64. @@ -614,8 +614,6 @@ class LclVarDsc unsigned char lvSingleDefDisqualifyReason = 'H'; #endif - unsigned char lvAllDefsAreNoGc : 1; // For pinned locals: true if all defs of this local are no-gc - #if FEATURE_MULTIREG_ARGS regNumber lvRegNumForSlot(unsigned slotNum) { @@ -1017,8 +1015,13 @@ class LclVarDsc return NO_CLASS_HANDLE; } #endif - - CORINFO_CLASS_HANDLE structHnd = GetLayout()->GetClassHandle(); + assert(m_layout != nullptr); +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + assert(varTypeIsStruct(TypeGet()) || (lvIsImplicitByRef && (TypeGet() == TYP_BYREF))); +#else + assert(varTypeIsStruct(TypeGet())); +#endif + CORINFO_CLASS_HANDLE structHnd = m_layout->GetClassHandle(); assert(structHnd != NO_CLASS_HANDLE); return structHnd; } @@ -1088,14 +1091,10 @@ class LclVarDsc return varTypeIsGC(lvType) || ((lvType == TYP_STRUCT) && m_layout->HasGCPtr()); } - // Returns the layout of a struct variable or implicit byref. + // Returns the layout of a struct variable. ClassLayout* GetLayout() const { -#if FEATURE_IMPLICIT_BYREFS - assert(varTypeIsStruct(TypeGet()) || (lvIsImplicitByRef && (TypeGet() == TYP_BYREF))); -#else - assert(varTypeIsStruct(TypeGet())); -#endif + assert(varTypeIsStruct(lvType)); return m_layout; } @@ -1243,16 +1242,6 @@ class IntegralRange assert(lowerBound <= upperBound); } - SymbolicIntegerValue GetLowerBound() - { - return m_lowerBound; - } - - SymbolicIntegerValue GetUpperBound() - { - return m_upperBound; - } - bool Contains(int64_t value) const; bool Contains(IntegralRange other) const @@ -1831,7 +1820,6 @@ class Compiler friend class MorphInitBlockHelper; friend class MorphCopyBlockHelper; friend class CallArgs; - friend class IndirectCallTransformer; #ifdef FEATURE_HW_INTRINSICS friend struct HWIntrinsicInfo; @@ -1894,6 +1882,11 @@ class Compiler // bool IsHfa(CORINFO_CLASS_HANDLE hClass); + bool IsHfa(GenTree* tree); + + var_types GetHfaType(GenTree* tree); + unsigned GetHfaCount(GenTree* tree); + var_types GetHfaType(CORINFO_CLASS_HANDLE hClass); unsigned GetHfaCount(CORINFO_CLASS_HANDLE hClass); @@ -2276,7 +2269,7 @@ class Compiler GenTree* gtNewIndOfIconHandleNode(var_types indType, size_t value, GenTreeFlags iconFlags, bool isInvariant); - GenTreeIntCon* gtNewIconHandleNode(size_t value, GenTreeFlags flags, FieldSeqNode* fields = nullptr); + GenTree* gtNewIconHandleNode(size_t value, GenTreeFlags flags, FieldSeqNode* fields = nullptr); GenTreeFlags gtTokenToIconFlags(unsigned token); @@ -3293,8 +3286,22 @@ class Compiler } #endif // TARGET_X86 - bool lvaIsImplicitByRefLocal(unsigned lclNum) const; - bool lvaIsLocalImplicitlyAccessedByRef(unsigned lclNum) const; + // For x64 this is 3, 5, 6, 7, >8 byte structs that are passed by reference. + // For ARM64, this is structs larger than 16 bytes that are passed by reference. + bool lvaIsImplicitByRefLocal(unsigned varNum) + { +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + LclVarDsc* varDsc = lvaGetDesc(varNum); + if (varDsc->lvIsImplicitByRef) + { + assert(varDsc->lvIsParam); + + assert(varTypeIsStruct(varDsc) || (varDsc->lvType == TYP_BYREF)); + return true; + } +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + return false; + } // Returns true if this local var is a multireg struct bool lvaIsMultiregStruct(LclVarDsc* varDsc, bool isVararg); @@ -3550,18 +3557,6 @@ class Compiler bool isExplicitTailCall, IL_OFFSET ilOffset = BAD_IL_OFFSET); - bool impConsiderCallProbe(GenTreeCall* call, IL_OFFSET ilOffset); - - enum class GDVProbeType - { - None, - ClassProfile, - MethodProfile, - MethodAndClassProfile, - }; - - GDVProbeType compClassifyGDVProbeType(GenTreeCall* call); - //========================================================================= // PROTECTED //========================================================================= @@ -3857,7 +3852,10 @@ class Compiler var_types impNormStructType(CORINFO_CLASS_HANDLE structHnd, CorInfoType* simdBaseJitType = nullptr); - GenTree* impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel); + GenTree* impNormStructVal(GenTree* structVal, + CORINFO_CLASS_HANDLE structHnd, + unsigned curLevel, + bool forceNormalization = false); GenTree* impTokenToHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool* pRuntimeLookup = nullptr, @@ -5376,6 +5374,13 @@ class Compiler void* pCallBackData = nullptr, bool computeStack = false); + // An fgWalkPreFn that looks for expressions that have inline throws in + // minopts mode. Basically it looks for tress with gtOverflowEx() or + // GTF_IND_RNGCHK. It returns WALK_ABORT if one is found. It + // returns WALK_SKIP_SUBTREES if GTF_EXCEPT is not set (assumes flags + // properly propagated to parent trees). It returns WALK_CONTINUE + // otherwise. + static fgWalkResult fgChkThrowCB(GenTree** pTree, Compiler::fgWalkData* data); static fgWalkResult fgChkLocAllocCB(GenTree** pTree, Compiler::fgWalkData* data); static fgWalkResult fgChkQmarkCB(GenTree** pTree, Compiler::fgWalkData* data); @@ -5440,7 +5445,7 @@ class Compiler bool fgGetProfileWeightForBasicBlock(IL_OFFSET offset, weight_t* weight); Instrumentor* fgCountInstrumentor; - Instrumentor* fgHistogramInstrumentor; + Instrumentor* fgClassInstrumentor; PhaseStatus fgPrepareToInstrumentMethod(); PhaseStatus fgInstrumentMethod(); @@ -5448,6 +5453,12 @@ class Compiler void fgIncorporateBlockCounts(); void fgIncorporateEdgeCounts(); + CORINFO_CLASS_HANDLE getRandomClass(ICorJitInfo::PgoInstrumentationSchema* schema, + UINT32 countSchemaItems, + BYTE* pInstrumentationData, + int32_t ilOffset, + CLRRandom* random); + public: const char* fgPgoFailReason; bool fgPgoDisabled; @@ -5638,10 +5649,7 @@ class Compiler void fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg); GenTree* fgMorphLocal(GenTreeLclVarCommon* lclNode); -#ifdef TARGET_X86 GenTree* fgMorphExpandStackArgForVarArgs(GenTreeLclVarCommon* lclNode); -#endif // TARGET_X86 - GenTree* fgMorphExpandImplicitByRefArg(GenTreeLclVarCommon* lclNode); GenTree* fgMorphLocalVar(GenTree* tree, bool forceRemorph); public: @@ -5686,7 +5694,6 @@ class Compiler Statement* paramAssignmentInsertionPoint); GenTree* fgMorphCall(GenTreeCall* call); GenTree* fgExpandVirtualVtableCallTarget(GenTreeCall* call); - void fgMorphCallInline(GenTreeCall* call, InlineResult* result); void fgMorphCallInlineHelper(GenTreeCall* call, InlineResult* result, InlineContext** createdContext); #if DEBUG @@ -5708,10 +5715,8 @@ class Compiler GenTree* fgMorphForRegisterFP(GenTree* tree); GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac = nullptr); GenTree* fgOptimizeCast(GenTreeCast* cast); - GenTree* fgOptimizeCastOnAssignment(GenTreeOp* asg); GenTree* fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp); GenTree* fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp); - GenTree* fgOptimizeRelationalComparisonWithFullRangeConst(GenTreeOp* cmp); #ifdef FEATURE_HW_INTRINSICS GenTree* fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node); #endif @@ -5858,6 +5863,10 @@ class Compiler // promoted, create new promoted struct temps. void fgRetypeImplicitByRefArgs(); + // Rewrite appearances of implicit byrefs (manifest the implied additional level of indirection). + bool fgMorphImplicitByRefArgs(GenTree* tree); + GenTree* fgMorphImplicitByRefArgs(GenTree* tree, bool isAddr); + // Clear up annotations for any struct promotion temps created for implicit byrefs. void fgMarkDemotedImplicitByRefArgs(); @@ -5892,8 +5901,6 @@ class Compiler bool gtIsTypeHandleToRuntimeTypeHandleHelper(GenTreeCall* call, CorInfoHelpFunc* pHelper = nullptr); bool gtIsActiveCSE_Candidate(GenTree* tree); - ExceptionSetFlags gtCollectExceptions(GenTree* tree); - bool fgIsBigOffset(size_t offset); bool fgNeedReturnSpillTemp(); @@ -5929,11 +5936,13 @@ class Compiler VNSet* m_pHoistedInCurLoop; public: + // Value numbers of expressions that have been hoisted in parent loops in the loop nest. + VNSet m_hoistedInParentLoops; + // Value numbers of expressions that have been hoisted in the current (or most recent) loop in the nest. // Previous decisions on loop-invariance of value numbers in the current loop. VNSet m_curLoopVnInvariantCache; - // Get the VN cache for current loop VNSet* GetHoistedInCurLoop(Compiler* comp) { if (m_pHoistedInCurLoop == nullptr) @@ -5943,35 +5952,35 @@ class Compiler return m_pHoistedInCurLoop; } - // Return the so far collected VNs in cache for current loop and reset it. - void ResetHoistedInCurLoop() + VNSet* ExtractHoistedInCurLoop() { + VNSet* res = m_pHoistedInCurLoop; m_pHoistedInCurLoop = nullptr; - JITDUMP("Resetting m_pHoistedInCurLoop\n"); + return res; } LoopHoistContext(Compiler* comp) - : m_pHoistedInCurLoop(nullptr), m_curLoopVnInvariantCache(comp->getAllocatorLoopHoist()) + : m_pHoistedInCurLoop(nullptr) + , m_hoistedInParentLoops(comp->getAllocatorLoopHoist()) + , m_curLoopVnInvariantCache(comp->getAllocatorLoopHoist()) { } }; - // Do hoisting of all loops nested within loop "lnum" (an index into the optLoopTable), followed - // by the loop "lnum" itself. - // - // "m_pHoistedInCurLoop" helps a lot in eliminating duplicate expressions getting hoisted - // and reducing the count of total expressions hoisted out of loop. When calculating the - // profitability, we compare this with number of registers and hence, lower the number of expressions - // getting hoisted, better chances that they will get enregistered and CSE considering them. - // + // Do hoisting for loop "lnum" (an index into the optLoopTable), and all loops nested within it. + // Tracks the expressions that have been hoisted by containing loops by temporarily recording their + // value numbers in "m_hoistedInParentLoops". This set is not modified by the call. void optHoistLoopNest(unsigned lnum, LoopHoistContext* hoistCtxt); // Do hoisting for a particular loop ("lnum" is an index into the optLoopTable.) - // Returns the new preheaders created. - void optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt, BasicBlockList* existingPreHeaders); + // Assumes that expressions have been hoisted in containing loops if their value numbers are in + // "m_hoistedInParentLoops". + // + void optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt); // Hoist all expressions in "blocks" that are invariant in loop "loopNum" (an index into the optLoopTable) - // outside of that loop. + // outside of that loop. Exempt expressions whose value number is in "m_hoistedInParentLoops"; add VN's of hoisted + // expressions to "hoistInLoop". void optHoistLoopBlocks(unsigned loopNum, ArrayStack* blocks, LoopHoistContext* hoistContext); // Return true if the tree looks profitable to hoist out of loop 'lnum'. @@ -6348,23 +6357,12 @@ class Compiler // unshared with any other loop. Returns "true" iff the flowgraph has been modified bool optCanonicalizeLoop(unsigned char loopInd); - enum class LoopCanonicalizationOption - { - Outer, - Current - }; - - bool optCanonicalizeLoopCore(unsigned char loopInd, LoopCanonicalizationOption option); - // Requires "l1" to be a valid loop table index, and not "BasicBlock::NOT_IN_LOOP". // Requires "l2" to be a valid loop table index, or else "BasicBlock::NOT_IN_LOOP". // Returns true iff "l2" is not NOT_IN_LOOP, and "l1" contains "l2". // A loop contains itself. bool optLoopContains(unsigned l1, unsigned l2) const; - // Returns the lpEntry for given preheader block of a loop - BasicBlock* optLoopEntry(BasicBlock* preHeader); - // Updates the loop table by changing loop "loopInd", whose head is required // to be "from", to be "to". Also performs this transformation for any // loop nested in "loopInd" that shares the same head as "loopInd". @@ -6817,21 +6815,13 @@ class Compiler optMethodFlags |= OMF_HAS_GUARDEDDEVIRT; } - void pickGDV(GenTreeCall* call, - IL_OFFSET ilOffset, - bool isInterface, - CORINFO_CLASS_HANDLE* classGuess, - CORINFO_METHOD_HANDLE* methodGuess, - unsigned* likelihood); - void considerGuardedDevirtualization(GenTreeCall* call, IL_OFFSET ilOffset, bool isInterface, CORINFO_METHOD_HANDLE baseMethod, CORINFO_CLASS_HANDLE baseClass, - CORINFO_CONTEXT_HANDLE* pContextHandle); - - bool isCompatibleMethodGDV(GenTreeCall* call, CORINFO_METHOD_HANDLE gdvTarget); + CORINFO_CONTEXT_HANDLE* pContextHandle DEBUGARG(CORINFO_CLASS_HANDLE objClass) + DEBUGARG(const char* objClassName)); void addGuardedDevirtualizationCandidate(GenTreeCall* call, CORINFO_METHOD_HANDLE methodHandle, @@ -7274,7 +7264,6 @@ class Compiler GenTree* optConstantAssertionProp(AssertionDsc* curAssertion, GenTreeLclVarCommon* tree, Statement* stmt DEBUGARG(AssertionIndex index)); - bool optIsProfitableToSubstitute(GenTreeLclVarCommon* lcl, BasicBlock* lclBlock, GenTree* value); bool optZeroObjAssertionProp(GenTree* tree, ASSERT_VALARG_TP assertions); // Assertion propagation functions. @@ -7660,7 +7649,7 @@ class Compiler // ICorJitInfo wrappers - void eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSectionAlignment); + void eeAllocMem(AllocMemArgs* args); void eeReserveUnwindInfo(bool isFunclet, bool isColdCode, ULONG unwindSize); @@ -8017,6 +8006,10 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX void unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode); void unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pColdCode, bool isHotCode); +#ifdef DEBUG + void fakeUnwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode); +#endif // DEBUG + #endif // TARGET_AMD64 || (TARGET_X86 && FEATURE_EH_FUNCLETS) UNATIVE_OFFSET unwindGetCurrentOffset(FuncInfoDsc* func); @@ -9563,7 +9556,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX unsigned genCPU; // What CPU are we running on // Number of class profile probes in this method - unsigned compHandleHistogramProbeCount; + unsigned compClassProbeCount; } info; diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index f6fa0e2d946b6..2fe7c10574c6b 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -902,8 +902,9 @@ inline GenTree* Compiler::gtNewLargeOperNode(genTreeOps oper, var_types type, Ge * that may need to be fixed up). */ -inline GenTreeIntCon* Compiler::gtNewIconHandleNode(size_t value, GenTreeFlags flags, FieldSeqNode* fields) +inline GenTree* Compiler::gtNewIconHandleNode(size_t value, GenTreeFlags flags, FieldSeqNode* fields) { + GenTree* node; assert((flags & (GTF_ICON_HDL_MASK | GTF_ICON_FIELD_OFF)) != 0); // Interpret "fields == NULL" as "not a field." @@ -912,7 +913,6 @@ inline GenTreeIntCon* Compiler::gtNewIconHandleNode(size_t value, GenTreeFlags f fields = FieldSeqStore::NotAField(); } - GenTreeIntCon* node; #if defined(LATE_DISASM) node = new (this, LargeOpOpcode()) GenTreeIntCon(TYP_I_IMPL, value, fields DEBUGARG(/*largeNode*/ true)); #else @@ -1123,16 +1123,19 @@ inline GenTreeField* Compiler::gtNewFieldRef(var_types type, CORINFO_FIELD_HANDL LclVarDsc* varDsc = lvaGetDesc(obj->AsUnOp()->gtOp1->AsLclVarCommon()); varDsc->lvFieldAccessed = 1; - - if (lvaIsImplicitByRefLocal(lvaGetLclNum(varDsc))) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + // These structs are passed by reference and can easily become global + // references if those references are exposed. We clear out + // address-exposure information for these parameters when they are + // converted into references in fgRetypeImplicitByRefArgs() so we do + // not have the necessary information in morph to know if these + // indirections are actually global references, so we have to be + // conservative here. + if (varDsc->lvIsParam) { - // These structs are passed by reference and can easily become global references if those - // references are exposed. We clear out address-exposure information for these parameters - // when they are converted into references in fgRetypeImplicitByRefArgs() so we do not have - // the necessary information in morph to know if these indirections are actually global - // references, so we have to be conservative here. fieldNode->gtFlags |= GTF_GLOB_REF; } +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) } else { @@ -1367,7 +1370,6 @@ inline void GenTree::SetOper(genTreeOps oper, ValueNumberUpdate vnUpdate) { case GT_CNS_INT: AsIntCon()->gtFieldSeq = FieldSeqStore::NotAField(); - INDEBUG(AsIntCon()->gtTargetHandle = 0); break; #if defined(TARGET_ARM) case GT_MUL_LONG: @@ -1877,10 +1879,10 @@ inline void LclVarDsc::incRefCnts(weight_t weight, Compiler* comp, RefCountState bool doubleWeight = lvIsTemp; -#if FEATURE_IMPLICIT_BYREFS +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // and, for the time being, implicit byref params doubleWeight |= lvIsImplicitByRef; -#endif // FEATURE_IMPLICIT_BYREFS +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) if (doubleWeight && (weight * 2 > weight)) { diff --git a/src/coreclr/jit/decomposelongs.cpp b/src/coreclr/jit/decomposelongs.cpp index d3be8577df4b4..781afe9dfbf32 100644 --- a/src/coreclr/jit/decomposelongs.cpp +++ b/src/coreclr/jit/decomposelongs.cpp @@ -931,6 +931,7 @@ GenTree* DecomposeLongs::DecomposeNeg(LIR::Use& use) Range().InsertAfter(loResult, zero, hiAdjust, hiResult); loResult->gtFlags |= GTF_SET_FLAGS; + hiAdjust->gtFlags |= GTF_USE_FLAGS; #elif defined(TARGET_ARM) @@ -941,6 +942,7 @@ GenTree* DecomposeLongs::DecomposeNeg(LIR::Use& use) Range().InsertAfter(loResult, hiResult); loResult->gtFlags |= GTF_SET_FLAGS; + hiResult->gtFlags |= GTF_USE_FLAGS; #endif @@ -995,6 +997,7 @@ GenTree* DecomposeLongs::DecomposeArith(LIR::Use& use) if ((oper == GT_ADD) || (oper == GT_SUB)) { loResult->gtFlags |= GTF_SET_FLAGS; + hiResult->gtFlags |= GTF_USE_FLAGS; if ((loResult->gtFlags & GTF_OVERFLOW) != 0) { diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index d09bffa0a5e9a..f8c437e326694 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1122,64 +1122,34 @@ void Compiler::eeDispLineInfos() * (e.g., host AMD64, target ARM64), then VM will get confused anyway. */ -void Compiler::eeAllocMem(AllocMemArgs* args, const UNATIVE_OFFSET roDataSectionAlignment) +void Compiler::eeAllocMem(AllocMemArgs* args) { #ifdef DEBUG + const UNATIVE_OFFSET hotSizeRequest = args->hotCodeSize; + const UNATIVE_OFFSET coldSizeRequest = args->coldCodeSize; - // Fake splitting implementation: place hot/cold code in contiguous section. - UNATIVE_OFFSET coldCodeOffset = 0; - if (JitConfig.JitFakeProcedureSplitting() && (args->coldCodeSize > 0)) + // Fake splitting implementation: place hot/cold code in contiguous section + if (JitConfig.JitFakeProcedureSplitting() && (coldSizeRequest > 0)) { - coldCodeOffset = args->hotCodeSize; - assert(coldCodeOffset > 0); - args->hotCodeSize += args->coldCodeSize; + args->hotCodeSize = hotSizeRequest + coldSizeRequest; args->coldCodeSize = 0; } - -#endif // DEBUG - -#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) - - // For arm64/LoongArch64, we want to allocate JIT data always adjacent to code similar to what native compiler does. - // This way allows us to use a single `ldr` to access such data like float constant/jmp table. - // For LoongArch64 using `pcaddi + ld` to access such data. - - UNATIVE_OFFSET roDataAlignmentDelta = 0; - if (args->roDataSize > 0) - { - roDataAlignmentDelta = AlignmentPad(args->hotCodeSize, roDataSectionAlignment); - } - - const UNATIVE_OFFSET roDataOffset = args->hotCodeSize + roDataAlignmentDelta; - args->hotCodeSize = roDataOffset + args->roDataSize; - args->roDataSize = 0; - -#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) +#endif info.compCompHnd->allocMem(args); #ifdef DEBUG - - if (JitConfig.JitFakeProcedureSplitting() && (coldCodeOffset > 0)) + if (JitConfig.JitFakeProcedureSplitting() && (coldSizeRequest > 0)) { - // Fix up cold code pointers. Cold section is adjacent to hot section. - assert(args->coldCodeBlock == nullptr); - assert(args->coldCodeBlockRW == nullptr); - args->coldCodeBlock = ((BYTE*)args->hotCodeBlock) + coldCodeOffset; - args->coldCodeBlockRW = ((BYTE*)args->hotCodeBlockRW) + coldCodeOffset; - } - -#endif // DEBUG + // Fix up hot/cold code pointers + args->coldCodeBlock = ((BYTE*)args->hotCodeBlock) + hotSizeRequest; + args->coldCodeBlockRW = ((BYTE*)args->hotCodeBlockRW) + hotSizeRequest; -#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) - - // Fix up data section pointers. - assert(args->roDataBlock == nullptr); - assert(args->roDataBlockRW == nullptr); - args->roDataBlock = ((BYTE*)args->hotCodeBlock) + roDataOffset; - args->roDataBlockRW = ((BYTE*)args->hotCodeBlockRW) + roDataOffset; - -#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + // Reset args' hot/cold code sizes in case caller reads them later + args->hotCodeSize = hotSizeRequest; + args->coldCodeSize = coldSizeRequest; + } +#endif } void Compiler::eeReserveUnwindInfo(bool isFunclet, bool isColdCode, ULONG unwindSize) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index eb846e06a0dc6..ebd4f2120585a 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -3894,33 +3894,15 @@ void emitter::emitDispJumpList() unsigned int jmpCount = 0; for (instrDescJmp* jmp = emitJumpList; jmp != nullptr; jmp = jmp->idjNext) { - printf("IG%02u IN%04x %3s[%u]", jmp->idjIG->igNum, jmp->idDebugOnlyInfo()->idNum, - codeGen->genInsDisplayName(jmp), jmp->idCodeSize()); - - if (!jmp->idIsBound()) - { - -#if defined(TARGET_ARM64) - if ((jmp->idInsFmt() == IF_LARGEADR) || (jmp->idInsFmt() == IF_LARGELDC)) - { - printf(" -> %s", getRegName(jmp->idReg1())); - } - else - { - printf(" -> IG%02u", ((insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel))->igNum); - } -#else - printf(" -> IG%02u", ((insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel))->igNum); - + printf("IG%02u IN%04x %3s[%u] -> IG%02u %s\n", jmp->idjIG->igNum, jmp->idDebugOnlyInfo()->idNum, + codeGen->genInsDisplayName(jmp), jmp->idCodeSize(), + ((insGroup*)emitCodeGetCookie(jmp->idAddr()->iiaBBlabel))->igNum, #if defined(TARGET_XARCH) - if (jmp->idjIsRemovableJmpCandidate) - { - printf(" ; removal candidate"); - } -#endif // TARGET_XARCH -#endif // !TARGET_ARM64 - } - printf("\n"); + jmp->idjIsRemovableJmpCandidate ? " ; removal candidate" : "" +#else + "" +#endif + ); jmpCount += 1; } printf(" total jump count: %u\n", jmpCount); @@ -4063,12 +4045,16 @@ void emitter::emitRecomputeIGoffsets() // // Arguments: // handle - a constant value to display a comment for -// cookie - the cookie stored with the handle // flags - a flag that the describes the handle // -void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlags flag) +void emitter::emitDispCommentForHandle(size_t handle, GenTreeFlags flag) { #ifdef DEBUG + if (handle == 0) + { + return; + } + #ifdef TARGET_XARCH const char* commentPrefix = " ;"; #else @@ -4076,35 +4062,8 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag #endif flag &= GTF_ICON_HDL_MASK; - - if (cookie != 0) - { - if (flag == GTF_ICON_FTN_ADDR) - { - const char* className = nullptr; - const char* methName = - emitComp->eeGetMethodName(reinterpret_cast(cookie), &className); - printf("%s code for %s:%s", commentPrefix, className, methName); - return; - } - - if ((flag == GTF_ICON_STATIC_HDL) || (flag == GTF_ICON_STATIC_BOX_PTR)) - { - const char* className = nullptr; - const char* fieldName = - emitComp->eeGetFieldName(reinterpret_cast(cookie), &className); - printf("%s %s for %s%s%s", commentPrefix, flag == GTF_ICON_STATIC_HDL ? "data" : "box", className, - className != nullptr ? ":" : "", fieldName); - return; - } - } - - if (handle == 0) - { - return; - } - const char* str = nullptr; + if (flag == GTF_ICON_STR_HDL) { const WCHAR* wstr = emitComp->eeGetCPString(handle); @@ -4144,6 +4103,8 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag { str = emitComp->eeGetClassName(reinterpret_cast(handle)); } +#ifndef TARGET_XARCH + // These are less useful for xarch: else if (flag == GTF_ICON_CONST_PTR) { str = "const ptr"; @@ -4172,6 +4133,11 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag { str = "token handle"; } + else + { + str = "unknown"; + } +#endif // TARGET_XARCH if (str != nullptr) { @@ -4561,6 +4527,7 @@ void emitter::emitJumpDistBind() else if (emitIsUncondJump(jmp)) { // Nothing to do; we don't shrink these. + assert(jmp->idjShort); ssz = JMP_SIZE_SMALL; } else if (emitIsLoadLabel(jmp)) @@ -6263,13 +6230,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, coldCodeBlock = nullptr; - // This restricts the data alignment to: 4, 8, 16, or 32 bytes - // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem - uint32_t dataAlignment = emitConsDsc.alignment; - assert((dataSection::MIN_DATA_ALIGN <= dataAlignment) && (dataAlignment <= dataSection::MAX_DATA_ALIGN) && - isPow2(dataAlignment)); - - uint32_t codeAlignment = TARGET_POINTER_SIZE; + CorJitAllocMemFlag allocMemFlag = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN; #ifdef TARGET_X86 // @@ -6289,14 +6250,14 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, const weight_t scenarioHotWeight = 256.0; if (emitComp->fgCalledCount > (scenarioHotWeight * emitComp->fgProfileRunsCount())) { - codeAlignment = 16; + allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; } } else { if (emitTotalHotCodeSize <= 16) { - codeAlignment = 16; + allocMemFlag = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; } } #endif @@ -6308,46 +6269,61 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, if (emitComp->opts.OptimizationEnabled() && !emitComp->opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && (emitTotalHotCodeSize > 16) && emitComp->fgHasLoops) { - codeAlignment = 32; + allocMemFlag = CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN; } #endif -#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) - // For arm64/LoongArch64, we're going to put the data in the code section. So make sure the code section has - // adequate alignment. - if (emitConsDsc.dsdOffs > 0) - { - codeAlignment = max(codeAlignment, dataAlignment); - } -#endif - - // Note that we don't support forcing code alignment of 8 bytes on 32-bit platforms; an omission? - assert((TARGET_POINTER_SIZE <= codeAlignment) && (codeAlignment <= 32) && isPow2(codeAlignment)); + // This restricts the emitConsDsc.alignment to: 1, 2, 4, 8, 16, or 32 bytes + // Alignments greater than 32 would require VM support in ICorJitInfo::allocMem + assert(isPow2(emitConsDsc.alignment) && (emitConsDsc.alignment <= 32)); - CorJitAllocMemFlag allocMemFlagCodeAlign = CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN; - if (codeAlignment == 32) + if (emitConsDsc.alignment == 16) { - allocMemFlagCodeAlign = CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN; + allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN); } - else if (codeAlignment == 16) + else if (emitConsDsc.alignment == 32) { - allocMemFlagCodeAlign = CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN; + allocMemFlag = static_cast(allocMemFlag | CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN); } - CorJitAllocMemFlag allocMemFlagDataAlign = static_cast(0); - if (dataAlignment == 16) + AllocMemArgs args; + memset(&args, 0, sizeof(args)); + +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + // For arm64/LoongArch64, we want to allocate JIT data always adjacent to code similar to what native compiler does. + // This way allows us to use a single `ldr` to access such data like float constant/jmp table. + // For LoongArch64 using `pcaddi + ld` to access such data. + if (emitTotalColdCodeSize > 0) { - allocMemFlagDataAlign = CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN; + // JIT data might be far away from the cold code. + NYI("Need to handle fix-up to data from cold code."); } - else if (dataAlignment == 32) + + UNATIVE_OFFSET roDataAlignmentDelta = 0; + if (emitConsDsc.dsdOffs && (emitConsDsc.alignment == TARGET_POINTER_SIZE)) { - allocMemFlagDataAlign = CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN; + UNATIVE_OFFSET roDataAlignment = TARGET_POINTER_SIZE; // 8 Byte align by default. + roDataAlignmentDelta = (UNATIVE_OFFSET)ALIGN_UP(emitTotalHotCodeSize, roDataAlignment) - emitTotalHotCodeSize; + assert((roDataAlignmentDelta == 0) || (roDataAlignmentDelta == 4)); } - CorJitAllocMemFlag allocMemFlag = static_cast(allocMemFlagCodeAlign | allocMemFlagDataAlign); + args.hotCodeSize = emitTotalHotCodeSize + roDataAlignmentDelta + emitConsDsc.dsdOffs; + args.coldCodeSize = emitTotalColdCodeSize; + args.roDataSize = 0; + args.xcptnsCount = xcptnsCount; + args.flag = allocMemFlag; + + emitComp->eeAllocMem(&args); - AllocMemArgs args; - memset(&args, 0, sizeof(args)); + codeBlock = (BYTE*)args.hotCodeBlock; + codeBlockRW = (BYTE*)args.hotCodeBlockRW; + coldCodeBlock = (BYTE*)args.coldCodeBlock; + coldCodeBlockRW = (BYTE*)args.coldCodeBlockRW; + + consBlock = codeBlock + emitTotalHotCodeSize + roDataAlignmentDelta; + consBlockRW = codeBlockRW + emitTotalHotCodeSize + roDataAlignmentDelta; + +#else args.hotCodeSize = emitTotalHotCodeSize; args.coldCodeSize = emitTotalColdCodeSize; @@ -6355,7 +6331,7 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, args.xcptnsCount = xcptnsCount; args.flag = allocMemFlag; - emitComp->eeAllocMem(&args, emitConsDsc.alignment); + emitComp->eeAllocMem(&args); codeBlock = (BYTE*)args.hotCodeBlock; codeBlockRW = (BYTE*)args.hotCodeBlockRW; @@ -6364,27 +6340,13 @@ unsigned emitter::emitEndCodeGen(Compiler* comp, consBlock = (BYTE*)args.roDataBlock; consBlockRW = (BYTE*)args.roDataBlockRW; +#endif + #ifdef DEBUG if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN) != 0) { assert(((size_t)codeBlock & 31) == 0); } -#if 0 - // TODO: we should be able to assert the following, but it appears crossgen2 doesn't respect them, - // or maybe it respects them in the written image but not in the buffer pointer given to the JIT. - if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) != 0) - { - assert(((size_t)codeBlock & 15) == 0); - } - if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN) != 0) - { - assert(((size_t)consBlock & 31) == 0); - } - if ((allocMemFlag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) != 0) - { - assert(((size_t)consBlock & 15) == 0); - } -#endif // 0 #endif // if (emitConsDsc.dsdOffs) @@ -7283,12 +7245,7 @@ UNATIVE_OFFSET emitter::emitDataGenBeg(unsigned size, unsigned alignment, var_ty } assert((secOffs % alignment) == 0); - if (emitConsDsc.alignment < alignment) - { - JITDUMP("Increasing data section alignment from %u to %u for type %s\n", emitConsDsc.alignment, alignment, - varTypeName(dataType)); - emitConsDsc.alignment = alignment; - } + emitConsDsc.alignment = max(emitConsDsc.alignment, alignment); /* Advance the current offset */ emitConsDsc.dsdOffs += size; @@ -7686,7 +7643,7 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) if (emitComp->opts.disAsm) { - emitDispDataSec(sec, dst); + emitDispDataSec(sec); } unsigned secNum = 0; @@ -7807,14 +7764,13 @@ void emitter::emitOutputDataSec(dataSecDsc* sec, BYTE* dst) // // Arguments: // section - the data section description -// dst - address of the data section // // Notes: // The output format attempts to mirror typical assembler syntax. // Data section entries lack type information so float/double entries // are displayed as if they are integers/longs. // -void emitter::emitDispDataSec(dataSecDsc* section, BYTE* dst) +void emitter::emitDispDataSec(dataSecDsc* section) { printf("\n"); @@ -7822,17 +7778,11 @@ void emitter::emitDispDataSec(dataSecDsc* section, BYTE* dst) for (dataSection* data = section->dsdList; data != nullptr; data = data->dsNext) { - if (emitComp->opts.disAddr) - { - printf("; @" FMT_ADDR "\n", DBG_ADDR(dst)); - } - const char* labelFormat = "%-7s"; char label[64]; sprintf_s(label, ArrLen(label), "RWD%02u", offset); printf(labelFormat, label); offset += data->dsSize; - dst += data->dsSize; if ((data->dsType == dataSection::blockRelative32) || (data->dsType == dataSection::blockAbsoluteAddr)) { diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index d44fd1bd572ee..fc90bd96d6909 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -523,7 +523,7 @@ class emitter void emitRecomputeIGoffsets(); - void emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlags flags); + void emitDispCommentForHandle(size_t handle, GenTreeFlags flags); /************************************************************************/ /* The following describes a single instruction */ @@ -554,7 +554,7 @@ class emitter #endif // TARGET_XARCH -#ifdef DEBUG // This information is used in DEBUG builds for additional diagnostics +#ifdef DEBUG // This information is used in DEBUG builds to display the method name for call instructions struct instrDesc; @@ -997,7 +997,7 @@ class emitter case IF_LARGELDC: if (isVectorRegister(idReg1())) { - // (adrp + ldr + fmov) or (adrp + add + ld1) + // adrp + ldr + fmov size = 12; } else @@ -2555,7 +2555,7 @@ class emitter void emitOutputDataSec(dataSecDsc* sec, BYTE* dst); #ifdef DEBUG - void emitDispDataSec(dataSecDsc* section, BYTE* dst); + void emitDispDataSec(dataSecDsc* section); #endif /************************************************************************/ diff --git a/src/coreclr/jit/emitarm.cpp b/src/coreclr/jit/emitarm.cpp index 5e172a0914a6d..ccf3ddff35709 100644 --- a/src/coreclr/jit/emitarm.cpp +++ b/src/coreclr/jit/emitarm.cpp @@ -7678,62 +7678,6 @@ void emitter::emitDispInsHelp( printf("\n"); } -/***************************************************************************** - * - * Handles printing of LARGEJMP pseudo-instruction. - */ - -void emitter::emitDispLargeJmp( - instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig) -{ - // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very - // difficult to find bug. - - instrDescJmp idJmp; - instrDescJmp* pidJmp = &idJmp; - - memset(&idJmp, 0, sizeof(idJmp)); - - pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the - // conditional - // instruction - pidJmp->idInsFmt(IF_T1_K); - pidJmp->idInsSize(emitInsSize(IF_T1_K)); - pidJmp->idjShort = 1; - pidJmp->idAddr()->iiaSetInstrCount(1); - pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field - - size_t bcondSizeOrZero = (code == NULL) ? 0 : 2; // branch is 2 bytes - emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, code, bcondSizeOrZero, - NULL /* force display of pc-relative branch */); - - code += bcondSizeOrZero; - offset += 2; - - // Next, display the unconditional branch - - // Reset the local instrDesc - memset(&idJmp, 0, sizeof(idJmp)); - - pidJmp->idIns(INS_b); - pidJmp->idInsFmt(IF_T2_J2); - pidJmp->idInsSize(emitInsSize(IF_T2_J2)); - pidJmp->idjShort = 0; - if (id->idIsBound()) - { - pidJmp->idSetIsBound(); - pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel; - } - else - { - pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel; - } - pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field - - size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes - emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig); -} - //-------------------------------------------------------------------- // emitDispIns: Dump the given instruction to jitstdout. // @@ -7770,7 +7714,53 @@ void emitter::emitDispIns( // // These instructions don't exist in the actual instruction stream, so we need to fake them // up to display them. - emitDispLargeJmp(id, isNew, doffs, asmfm, offset, code, sz, ig); + // + // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very + // difficult to find bug. + + instrDescJmp idJmp; + instrDescJmp* pidJmp = &idJmp; + + memset(&idJmp, 0, sizeof(idJmp)); + + pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the + // conditional + // instruction + pidJmp->idInsFmt(IF_T1_K); + pidJmp->idInsSize(emitInsSize(IF_T1_K)); + pidJmp->idjShort = 1; + pidJmp->idAddr()->iiaSetInstrCount(1); + pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field + + size_t bcondSizeOrZero = (code == NULL) ? 0 : 2; // branch is 2 bytes + emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, code, bcondSizeOrZero, + NULL /* force display of pc-relative branch */); + + code += bcondSizeOrZero; + offset += 2; + + // Next, display the unconditional branch + + // Reset the local instrDesc + memset(&idJmp, 0, sizeof(idJmp)); + + pidJmp->idIns(INS_b); + pidJmp->idInsFmt(IF_T2_J2); + pidJmp->idInsSize(emitInsSize(IF_T2_J2)); + pidJmp->idjShort = 0; + if (id->idIsBound()) + { + pidJmp->idSetIsBound(); + pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel; + } + else + { + pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel; + } + pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field + + size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes + emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig); } else { diff --git a/src/coreclr/jit/emitarm.h b/src/coreclr/jit/emitarm.h index c40c5fb85f9c5..09133a1d88f02 100644 --- a/src/coreclr/jit/emitarm.h +++ b/src/coreclr/jit/emitarm.h @@ -43,14 +43,6 @@ void emitDispAddrRR(regNumber reg1, regNumber reg2, emitAttr attr); void emitDispAddrRRI(regNumber reg1, regNumber reg2, int imm, emitAttr attr); void emitDispAddrPUW(regNumber reg, int imm, insOpts opt, emitAttr attr); void emitDispGC(emitAttr attr); -void emitDispLargeJmp(instrDesc* id, - bool isNew, - bool doffs, - bool asmfm, - unsigned offs = 0, - BYTE* code = 0, - size_t sz = 0, - insGroup* ig = NULL); void emitDispInsHelp(instrDesc* id, bool isNew, diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index b0bf1769d1bd0..864ba862edddd 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -3740,8 +3740,7 @@ void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, - insOpts opt /* = INS_OPTS_NONE */ - DEBUGARG(size_t targetHandle /* = 0 */) DEBUGARG(GenTreeFlags gtFlags /* = GTF_EMPTY */)) + insOpts opt /* = INS_OPTS_NONE */ DEBUGARG(GenTreeFlags gtFlags)) { emitAttr size = EA_SIZE(attr); emitAttr elemsize = EA_UNKNOWN; @@ -3991,11 +3990,7 @@ void emitter::emitIns_R_I(instruction ins, id->idInsOpt(opt); id->idReg1(reg); - -#ifdef DEBUG - id->idDebugOnlyInfo()->idMemCookie = targetHandle; - id->idDebugOnlyInfo()->idFlags = gtFlags; -#endif + INDEBUG(id->idDebugOnlyInfo()->idFlags = gtFlags); dispIns(id); appendToCurIG(id); @@ -4508,16 +4503,14 @@ void emitter::emitIns_R_R( case INS_str: case INS_strb: case INS_strh: + + case INS_cmp: case INS_cmn: case INS_tst: assert(insOptsNone(opt)); emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE); return; - case INS_cmp: - emitIns_R_R_I(ins, attr, reg1, reg2, 0, opt); - return; - case INS_staddb: emitIns_R_R_R(INS_ldaddb, attr, reg1, REG_ZR, reg2); return; @@ -4934,13 +4927,8 @@ void emitter::emitIns_R_R( * Add an instruction referencing a register and two constants. */ -void emitter::emitIns_R_I_I(instruction ins, - emitAttr attr, - regNumber reg, - ssize_t imm1, - ssize_t imm2, - insOpts opt /* = INS_OPTS_NONE */ - DEBUGARG(size_t targetHandle /* = 0 */) DEBUGARG(GenTreeFlags gtFlags /* = 0 */)) +void emitter::emitIns_R_I_I( + instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */) { emitAttr size = EA_SIZE(attr); insFormat fmt = IF_NONE; @@ -5027,11 +5015,6 @@ void emitter::emitIns_R_I_I(instruction ins, id->idReg1(reg); -#ifdef DEBUG - id->idDebugOnlyInfo()->idFlags = gtFlags; - id->idDebugOnlyInfo()->idMemCookie = targetHandle; -#endif - dispIns(id); appendToCurIG(id); } @@ -8438,12 +8421,10 @@ void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount) switch (ins) { case INS_bl_local: - idjShort = true; - FALLTHROUGH; case INS_b: // Unconditional jump is a single form. - // Assume is long in case we cross hot/cold sections. - fmt = IF_BI_0A; + idjShort = true; + fmt = IF_BI_0A; break; case INS_beq: @@ -8488,6 +8469,7 @@ void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount) id->idAddr()->iiaBBlabel = dst; // Skip unconditional jump that has a single form. + // TODO-ARM64-NYI: enable hot/cold splittingNYI. // The target needs to be relocated. if (!idjShort) { @@ -9817,67 +9799,38 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) { // Update addrReg with the reserved integer register // since we cannot use dstReg (vector) to load constant directly from memory. - - // If loading a 16-byte value, we will need to load directly into dstReg. - // Thus, encode addrReg for the ld1 instruction. - if (opSize == EA_16BYTE) - { - addrReg = encodingSPtoZR(id->idReg2()); - } - else - { - addrReg = id->idReg2(); - } - + addrReg = id->idReg2(); assert(isGeneralRegister(addrReg)); } - ins = INS_adrp; fmt = IF_DI_1E; dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg); + // ldr x, [x, page offs] -- load constant from page address + page offset into integer register. ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits assert(isValidUimm12(imm12)); + ins = INS_ldr; + fmt = IF_LS_2B; + dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize); - // Special case: emit add + ld1 instructions for loading 16-byte data into vector register. - if (isVectorRegister(dstReg) && (opSize == EA_16BYTE)) - { - const emitAttr elemSize = EA_1BYTE; - const insOpts opt = optMakeArrangement(opSize, elemSize); - - assert(isGeneralRegisterOrSP(addrReg)); - assert(isValidVectorElemsize(elemSize)); - assert(isValidArrangement(opSize, opt)); - - // Calculate page addr + page offs, then emit ld1 instruction. - dst = emitOutputVectorConstant(dst, imm12, dstReg, addrReg, opSize, elemSize); - } - else + // fmov v, d -- copy constant in integer register to vector register. + // This is needed only for vector constant. + if (addrReg != dstReg) { - // ldr x, [x, 0] -- load constant from address into integer register. - ins = INS_ldr; - fmt = IF_LS_2B; - dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize); + // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn + // (scalar, from general) + assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg)); + ins = INS_fmov; + fmt = IF_DV_2I; + code_t code = emitInsCode(ins, fmt); - // fmov v, d -- copy constant in integer register to vector register. - // This is needed only for vector constant. - if (addrReg != dstReg) + code |= insEncodeReg_Vd(dstReg); // ddddd + code |= insEncodeReg_Rn(addrReg); // nnnnn + if (id->idOpSize() == EA_8BYTE) { - // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn - // (scalar, from general) - assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg)); - ins = INS_fmov; - fmt = IF_DV_2I; - code_t code = emitInsCode(ins, fmt); - - code |= insEncodeReg_Vd(dstReg); // ddddd - code |= insEncodeReg_Rn(addrReg); // nnnnn - if (id->idOpSize() == EA_8BYTE) - { - code |= 0x80400000; // X ... X - } - dst += emitOutput_Instr(dst, code); + code |= 0x80400000; // X ... X } + dst += emitOutput_Instr(dst, code); } } } @@ -9980,6 +9933,12 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) /* For forward jumps, record the address of the distance value */ id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL; + if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs)) + { + assert(!id->idjShort); + NYI_ARM64("Relocation Support for long address"); + } + assert(insOptsNone(id->idInsOpt())); if (isJump) @@ -9990,114 +9949,75 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) assert(!id->idjKeepLong); assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false); assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B)); - dst = emitOutputShortBranch(dst, ins, fmt, distVal, id); } else { - // Long conditional/unconditional jump - - if (fmt == IF_LARGEJMP) - { - // This is a pseudo-instruction format representing a large conditional branch, to allow - // us to get a greater branch target range than we can get by using a straightforward conditional - // branch. It is encoded as a short conditional branch that branches around a long unconditional - // branch. - // - // Conceptually, we have: - // - // b L_target - // - // The code we emit is: - // - // b L_not // 4 bytes. Note that we reverse the condition. - // b L_target // 4 bytes - // L_not: - // - // Note that we don't actually insert any blocks: we simply encode "b L_not" as a branch with - // the correct offset. Note also that this works for both integer and floating-point conditions, because - // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example, - // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered). - - instruction reverseIns; - insFormat reverseFmt; - - switch (ins) - { - case INS_cbz: - reverseIns = INS_cbnz; - reverseFmt = IF_BI_1A; - break; - case INS_cbnz: - reverseIns = INS_cbz; - reverseFmt = IF_BI_1A; - break; - case INS_tbz: - reverseIns = INS_tbnz; - reverseFmt = IF_BI_1B; - break; - case INS_tbnz: - reverseIns = INS_tbz; - reverseFmt = IF_BI_1B; - break; - default: - reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins))); - reverseFmt = IF_BI_0B; - } - - dst = emitOutputShortBranch(dst, - reverseIns, // reverse the conditional instruction - reverseFmt, 8, /* 8 bytes from start of this large conditional - pseudo-instruction to L_not. */ - id); - - // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that. - ins = INS_b; - fmt = IF_BI_0A; - - // The distVal was computed based on the beginning of the pseudo-instruction, - // So subtract the size of the conditional branch so that it is relative to the - // unconditional branch. - distVal -= 4; - } + // Long conditional jump + assert(fmt == IF_LARGEJMP); + // This is a pseudo-instruction format representing a large conditional branch, to allow + // us to get a greater branch target range than we can get by using a straightforward conditional + // branch. It is encoded as a short conditional branch that branches around a long unconditional + // branch. + // + // Conceptually, we have: + // + // b L_target + // + // The code we emit is: + // + // b L_not // 4 bytes. Note that we reverse the condition. + // b L_target // 4 bytes + // L_not: + // + // Note that we don't actually insert any blocks: we simply encode "b L_not" as a branch with + // the correct offset. Note also that this works for both integer and floating-point conditions, because + // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example, + // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered). - assert(fmt == IF_BI_0A); - assert((distVal & 1) == 0); - code_t code = emitInsCode(ins, fmt); - const bool recordRelocation = emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs); + instruction reverseIns; + insFormat reverseFmt; - if (recordRelocation) - { - // dst isn't an actual final target location, just some intermediate - // location. Thus we cannot make any guarantees about distVal (not - // even the direction/sign). Instead we don't encode any offset and - // rely on the relocation to do all the work - } - else + switch (ins) { - // Branch offset encodings are scaled by 4. - noway_assert((distVal & 3) == 0); - distVal >>= 2; - noway_assert(isValidSimm26(distVal)); - - // Insert offset into unconditional branch instruction - distVal &= 0x3FFFFFFLL; - code |= distVal; + case INS_cbz: + reverseIns = INS_cbnz; + reverseFmt = IF_BI_1A; + break; + case INS_cbnz: + reverseIns = INS_cbz; + reverseFmt = IF_BI_1A; + break; + case INS_tbz: + reverseIns = INS_tbnz; + reverseFmt = IF_BI_1B; + break; + case INS_tbnz: + reverseIns = INS_tbz; + reverseFmt = IF_BI_1B; + break; + default: + reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins))); + reverseFmt = IF_BI_0B; } - const unsigned instrSize = emitOutput_Instr(dst, code); + dst = + emitOutputShortBranch(dst, + reverseIns, // reverse the conditional instruction + reverseFmt, + 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */ + id); - if (recordRelocation) - { - assert(id->idjKeepLong); - if (emitComp->info.compMatchedVM) - { - void* target = emitOffsetToPtr(dstOffs); - emitRecordRelocation((void*)dst, target, IMAGE_REL_ARM64_BRANCH26); - } - } + // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that. + ins = INS_b; + fmt = IF_BI_0A; - dst += instrSize; + // The distVal was computed based on the beginning of the pseudo-instruction, + // So subtract the size of the conditional branch so that it is relative to the + // unconditional branch. + distVal -= 4; } + + dst = emitOutputShortBranch(dst, ins, fmt, distVal, id); } else if (loadLabel) { @@ -10218,7 +10138,7 @@ BYTE* emitter::emitOutputShortConstant( ssize_t loBits = (imm & 3); noway_assert(loBits == 0); - ssize_t distVal = imm >> 2; // load offset encodings are scaled by 4. + ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4. noway_assert(isValidSimm19(distVal)); @@ -10286,33 +10206,6 @@ BYTE* emitter::emitOutputShortConstant( return dst; } - -/***************************************************************************** - * - * Output instructions to load a constant into a vector register. - */ -BYTE* emitter::emitOutputVectorConstant( - BYTE* dst, ssize_t imm, regNumber dstReg, regNumber addrReg, emitAttr opSize, emitAttr elemSize) -{ - // add addrReg, addrReg, page offs -- compute address = page addr + page offs. - code_t code = emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh) - code |= insEncodeDatasize(EA_8BYTE); // X - use EA_8BYTE, as we are calculating 64-bit address - code |= ((code_t)imm << 10); // iiiiiiiiiiii - code |= insEncodeReg_Rd(addrReg); // ddddd - code |= insEncodeReg_Rn(addrReg); // nnnnn - dst += emitOutput_Instr(dst, code); - - // ld1 dstReg, addrReg -- load constant at address in addrReg into dstReg. - code = emitInsCode(INS_ld1, IF_LS_2D); // LS_2D .Q.............. ....ssnnnnnttttt Vt Rn - code |= insEncodeVectorsize(opSize); // Q - code |= insEncodeVLSElemsize(elemSize); // ss - code |= insEncodeReg_Rn(addrReg); // nnnnn - code |= insEncodeReg_Vt(dstReg); // ttttt - dst += emitOutput_Instr(dst, code); - - return dst; -} - /***************************************************************************** * * Output a call instruction. @@ -12348,121 +12241,8 @@ void emitter::emitDispInsHex(instrDesc* id, BYTE* code, size_t sz) } } -/***************************************************************************** - * - * Handles printing of LARGEJMP pseudo-instruction. - */ - -void emitter::emitDispLargeJmp( - instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig) -{ - // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very - // difficult-to-find bug. - - instrDescJmp idJmp; - instrDescJmp* pidJmp = &idJmp; - - memset(&idJmp, 0, sizeof(idJmp)); - - const instruction ins = id->idIns(); - instruction reverseIns; - insFormat reverseFmt; - - // Reverse the conditional instruction. - switch (ins) - { - case INS_cbz: - reverseIns = INS_cbnz; - reverseFmt = IF_BI_1A; - break; - case INS_cbnz: - reverseIns = INS_cbz; - reverseFmt = IF_BI_1A; - break; - case INS_tbz: - reverseIns = INS_tbnz; - reverseFmt = IF_BI_1B; - break; - case INS_tbnz: - reverseIns = INS_tbz; - reverseFmt = IF_BI_1B; - break; - default: - reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins))); - reverseFmt = IF_BI_0B; - } - - pidJmp->idIns(reverseIns); - pidJmp->idInsFmt(reverseFmt); - pidJmp->idOpSize(id->idOpSize()); - pidJmp->idAddr()->iiaSetInstrCount(1); - pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // Share the idDebugOnlyInfo() field. - - const size_t bcondSizeOrZero = (pCode == NULL) ? 0 : 4; // Branch is 4 bytes. - emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, pCode, bcondSizeOrZero, - NULL /* force display of pc-relative branch */); - - pCode += bcondSizeOrZero; - offset += 4; - - // Next, display the unconditional branch. - - // Reset the local instrDesc. - memset(&idJmp, 0, sizeof(idJmp)); - - pidJmp->idIns(INS_b); - pidJmp->idInsFmt(IF_LARGEJMP); - - if (id->idIsBound()) - { - pidJmp->idSetIsBound(); - pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel; - } - else - { - pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel; - } - - pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // Share the idDebugOnlyInfo() field. - - const size_t brSizeOrZero = (pCode == NULL) ? 0 : 4; // Unconditional branch is 4 bytes. - emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, pCode, brSizeOrZero, ig); -} - -/***************************************************************************** - * - * Wrapper for emitter::emitDispInsHelp() that handles special large jump - * pseudo-instruction. - */ - -void emitter::emitDispIns( - instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig) -{ - // Special case: IF_LARGEJMP - - if ((id->idInsFmt() == IF_LARGEJMP) && id->idIsBound()) - { - // This is a pseudo-instruction format representing a large conditional branch. See the comment - // in emitter::emitOutputLJ() for the full description. - // - // For this pseudo-instruction, we will actually generate: - // - // b L_not // 4 bytes. Note that we reverse the condition. - // b L_target // 4 bytes. - // L_not: - // - // These instructions don't exist in the actual instruction stream, so we need to fake them - // up to display them. - emitDispLargeJmp(id, isNew, doffs, asmfm, offset, pCode, sz, ig); - } - else - { - emitDispInsHelp(id, isNew, doffs, asmfm, offset, pCode, sz, ig); - } -} - //-------------------------------------------------------------------- -// emitDispInsHelp: Dump the given instruction to jitstdout. +// emitDispIns: Dump the given instruction to jitstdout. // // Arguments: // id - The instruction @@ -12477,7 +12257,7 @@ void emitter::emitDispIns( // sz - The size of the instruction, used to display the encoded bytes. // ig - The instruction group containing the instruction. // -void emitter::emitDispInsHelp( +void emitter::emitDispIns( instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig) { if (EMITVERBOSE) @@ -12489,9 +12269,7 @@ void emitter::emitDispInsHelp( } if (pCode == NULL) - { sz = 0; - } if (!isNew && !asmfm && sz) { @@ -12601,34 +12379,23 @@ void emitter::emitDispInsHelp( break; case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00 - case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00 - { assert(insOptsNone(id->idInsOpt())); emitDispReg(id->idReg1(), size, true); - - if (fmt == IF_BI_1B) + if (id->idIsBound()) { - emitDispImm(emitGetInsSC(id), true); + emitPrintLabel(id->idAddr()->iiaIGlabel); } - - if (id->idAddr()->iiaHasInstrCount()) + else { - int instrCount = id->idAddr()->iiaGetInstrCount(); - - if (ig == nullptr) - { - printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount); - } - else - { - unsigned insNum = emitFindInsNum(ig, id); - UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1); - UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount); - ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs)); - printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount); - } + printf("L_M%03u_" FMT_BB, emitComp->compMethodID, id->idAddr()->iiaBBlabel->bbNum); } - else if (id->idIsBound()) + break; + + case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00 + assert(insOptsNone(id->idInsOpt())); + emitDispReg(id->idReg1(), size, true); + emitDispImm(emitGetInsSC(id), true); + if (id->idIsBound()) { emitPrintLabel(id->idAddr()->iiaIGlabel); } @@ -12636,8 +12403,7 @@ void emitter::emitDispInsHelp( { printf("L_M%03u_" FMT_BB, emitComp->compMethodID, id->idAddr()->iiaBBlabel->bbNum); } - } - break; + break; case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn assert(insOptsNone(id->idInsOpt())); @@ -12721,7 +12487,7 @@ void emitter::emitDispInsHelp( } else { - emitDispCommentForHandle(id->idDebugOnlyInfo()->idMemCookie, 0, id->idDebugOnlyInfo()->idFlags); + emitDispCommentForHandle(id->idDebugOnlyInfo()->idMemCookie, id->idDebugOnlyInfo()->idFlags); } break; @@ -12857,7 +12623,6 @@ void emitter::emitDispInsHelp( case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh) emitDispReg(id->idReg1(), size, true); emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt()); - emitDispCommentForHandle(0, id->idDebugOnlyInfo()->idMemCookie, id->idDebugOnlyInfo()->idFlags); break; case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw) @@ -12876,21 +12641,18 @@ void emitter::emitDispInsHelp( emitDispImm(hwi.immHW * 16, false); } } - emitDispCommentForHandle(0, id->idDebugOnlyInfo()->idMemCookie, id->idDebugOnlyInfo()->idFlags); break; case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s) emitDispReg(id->idReg1(), size, true); bmi.immNRS = (unsigned)emitGetInsSC(id); emitDispImm(emitDecodeBitMaskImm(bmi, size), false); - emitDispCommentForHandle(0, id->idDebugOnlyInfo()->idMemCookie, id->idDebugOnlyInfo()->idFlags); break; case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s) emitDispReg(encodingZRtoSP(id->idReg1()), size, true); bmi.immNRS = (unsigned)emitGetInsSC(id); emitDispImm(emitDecodeBitMaskImm(bmi, size), false); - emitDispCommentForHandle(0, id->idDebugOnlyInfo()->idMemCookie, id->idDebugOnlyInfo()->idFlags); break; case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh) diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index 4068fe3c25408..8970c15b3c090 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -23,10 +23,6 @@ static bool strictArmAsm; const char* emitVectorRegName(regNumber reg); -void emitDispInsHelp( - instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig); -void emitDispLargeJmp( - instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig); void emitDispInst(instruction ins); void emitDispImm(ssize_t imm, bool addComma, bool alwaysHex = false); void emitDispFloatZero(); @@ -730,8 +726,7 @@ void emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, - insOpts opt = INS_OPTS_NONE DEBUGARG(size_t targetHandle = 0) - DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY)); + insOpts opt = INS_OPTS_NONE DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY)); void emitIns_R_F(instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt = INS_OPTS_NONE); @@ -745,13 +740,8 @@ void emitIns_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, emitIns_R_R(ins, attr, reg1, reg2); } -void emitIns_R_I_I(instruction ins, - emitAttr attr, - regNumber reg1, - ssize_t imm1, - ssize_t imm2, - insOpts opt = INS_OPTS_NONE DEBUGARG(size_t targetHandle = 0) - DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY)); +void emitIns_R_I_I( + instruction ins, emitAttr attr, regNumber reg1, ssize_t imm1, ssize_t imm2, insOpts opt = INS_OPTS_NONE); void emitIns_R_R_I( instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt = INS_OPTS_NONE); @@ -877,8 +867,6 @@ BYTE* emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t d BYTE* emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg); BYTE* emitOutputShortConstant( BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg, emitAttr opSize); -BYTE* emitOutputVectorConstant( - BYTE* dst, ssize_t distVal, regNumber dstReg, regNumber addrReg, emitAttr opSize, emitAttr elemSize); /***************************************************************************** * diff --git a/src/coreclr/jit/emitloongarch64.cpp b/src/coreclr/jit/emitloongarch64.cpp index 57987606a903c..8e3802123dd5a 100644 --- a/src/coreclr/jit/emitloongarch64.cpp +++ b/src/coreclr/jit/emitloongarch64.cpp @@ -3912,7 +3912,7 @@ static const char* const RegNames[] = void emitter::emitDisInsName(code_t code, const BYTE* addr, instrDesc* id) { - const BYTE* insAdr = addr - writeableOffset; + const BYTE* insAdr = addr; const char* const CFregName[] = {"fcc0", "fcc1", "fcc2", "fcc3", "fcc4", "fcc5", "fcc6", "fcc7"}; unsigned int opcode = (code >> 26) & 0x3f; diff --git a/src/coreclr/jit/emitloongarch64.h b/src/coreclr/jit/emitloongarch64.h index da24986527182..d7e7cc5450acb 100644 --- a/src/coreclr/jit/emitloongarch64.h +++ b/src/coreclr/jit/emitloongarch64.h @@ -133,12 +133,6 @@ inline static bool isFloatReg(regNumber reg) return (reg >= REG_FP_FIRST && reg <= REG_FP_LAST); } -/************************************************************************/ -/* Output target-independent instructions */ -/************************************************************************/ - -void emitIns_J(instruction ins, BasicBlock* dst, int instrCount = 0); - /************************************************************************/ /* The public entry points to output instructions */ /************************************************************************/ diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index bd5b2d0defe6a..707c8fc25f7c3 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -3219,11 +3219,6 @@ void emitter::emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, id->idAddr()->iiaFieldHnd = fldHnd; id->idInsFmt(emitMapFmtForIns(emitMapFmtAtoM(fmt), ins)); - -#ifdef DEBUG - id->idDebugOnlyInfo()->idFlags = GTF_ICON_STATIC_HDL; - id->idDebugOnlyInfo()->idMemCookie = reinterpret_cast(fldHnd); -#endif } else if ((memBase != nullptr) && memBase->IsCnsIntOrI() && memBase->isContained()) { @@ -3284,14 +3279,6 @@ void emitter::emitHandleMemOp(GenTreeIndir* indir, instrDesc* id, insFormat fmt, // disp must have already been set in the instrDesc constructor. assert(emitGetInsAmdAny(id) == indir->Offset()); // make sure "disp" is stored properly } - -#ifdef DEBUG - if ((memBase != nullptr) && memBase->IsIconHandle() && memBase->isContained()) - { - id->idDebugOnlyInfo()->idFlags = memBase->gtFlags; - id->idDebugOnlyInfo()->idMemCookie = memBase->AsIntCon()->gtTargetHandle; - } -#endif } // Takes care of storing all incoming register parameters @@ -4139,10 +4126,7 @@ void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg) * Add an instruction referencing a register and a constant. */ -void emitter::emitIns_R_I(instruction ins, - emitAttr attr, - regNumber reg, - ssize_t val DEBUGARG(size_t targetHandle) DEBUGARG(GenTreeFlags gtFlags)) +void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t val DEBUGARG(GenTreeFlags gtFlags)) { emitAttr size = EA_SIZE(attr); @@ -4275,11 +4259,7 @@ void emitter::emitIns_R_I(instruction ins, id->idInsFmt(fmt); id->idReg1(reg); id->idCodeSize(sz); - -#ifdef DEBUG - id->idDebugOnlyInfo()->idFlags = gtFlags; - id->idDebugOnlyInfo()->idMemCookie = targetHandle; -#endif + INDEBUG(id->idDebugOnlyInfo()->idFlags = gtFlags); dispIns(id); emitCurIGsize += sz; @@ -9138,7 +9118,7 @@ void emitter::emitDispIns( { // (val < 0) printf("-0x%IX", -val); } - emitDispCommentForHandle(srcVal, id->idDebugOnlyInfo()->idMemCookie, id->idDebugOnlyInfo()->idFlags); + emitDispCommentForHandle(srcVal, id->idDebugOnlyInfo()->idFlags); } break; @@ -9209,9 +9189,6 @@ void emitter::emitDispIns( } printf("%s, %s", emitRegName(id->idReg1(), attr), sstr); emitDispAddrMode(id); - - emitDispCommentForHandle(emitGetInsAmdAny(id), id->idDebugOnlyInfo()->idMemCookie, - id->idDebugOnlyInfo()->idFlags); break; case IF_RRW_ARD_CNS: diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index c744e40dbd41e..754632bb1c089 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -330,10 +330,7 @@ void emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fdlHnd, int void emitIns_A(instruction ins, emitAttr attr, GenTreeIndir* indir); -void emitIns_R_I(instruction ins, - emitAttr attr, - regNumber reg, - ssize_t val DEBUGARG(size_t targetHandle = 0) DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY)); +void emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t val DEBUGARG(GenTreeFlags gtFlags = GTF_EMPTY)); void emitIns_Mov(instruction ins, emitAttr attr, regNumber dstReg, regNumber srgReg, bool canSkip); diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index 541bdc27e7c96..148dc02af9649 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -186,7 +186,7 @@ void Compiler::fgInit() fgPgoInlineeNoPgo = 0; fgPgoInlineeNoPgoSingleBlock = 0; fgCountInstrumentor = nullptr; - fgHistogramInstrumentor = nullptr; + fgClassInstrumentor = nullptr; fgPredListSortVector = nullptr; } diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index d59301991aaa6..fe0746aa26d72 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -274,7 +274,7 @@ void Compiler::fgNoteNonInlineCandidate(Statement* stmt, GenTreeCall* call) return; } - InlineResult inlineResult(this, call, nullptr, "fgNoteNonInlineCandidate", false); + InlineResult inlineResult(this, call, nullptr, "fgNoteNonInlineCandidate"); InlineObservation currentObservation = InlineObservation::CALLSITE_NOT_CANDIDATE; // Try and recover the reason left behind when the jit decided @@ -288,6 +288,7 @@ void Compiler::fgNoteNonInlineCandidate(Statement* stmt, GenTreeCall* call) // Propagate the prior failure observation to this result. inlineResult.NotePriorFailure(currentObservation); + inlineResult.SetReported(); if (call->gtCallType == CT_USER_FUNC) { diff --git a/src/coreclr/jit/fgopt.cpp b/src/coreclr/jit/fgopt.cpp index 360633d901e93..d0d4ae647ec98 100644 --- a/src/coreclr/jit/fgopt.cpp +++ b/src/coreclr/jit/fgopt.cpp @@ -3221,10 +3221,8 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block) if (verbose) { printf("\nConverting a switch (" FMT_BB ") with only one significant clause besides a default target to a " - "conditional branch. Before:\n", + "conditional branch\n", block->bbNum); - - gtDispTree(switchTree); } #endif // DEBUG @@ -3249,9 +3247,6 @@ bool Compiler::fgOptimizeSwitchBranches(BasicBlock* block) block->bbJumpDest = block->bbJumpSwt->bbsDstTab[0]; block->bbJumpKind = BBJ_COND; - JITDUMP("After:\n"); - DISPNODE(switchTree); - return true; } return returnvalue; diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index 4eb555a65ca94..bfd7000486c8b 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -1425,11 +1425,11 @@ void EfficientEdgeCountInstrumentor::Instrument(BasicBlock* block, Schema& schem } //------------------------------------------------------------------------ -// HandleHistogramProbeVisitor: invoke functor on each virtual call or cast-related +// ClassProbeVisitor: invoke functor on each virtual call or cast-related // helper calls in a tree // template -class HandleHistogramProbeVisitor final : public GenTreeVisitor> +class ClassProbeVisitor final : public GenTreeVisitor> { public: enum @@ -1440,17 +1440,26 @@ class HandleHistogramProbeVisitor final : public GenTreeVisitor(compiler), m_functor(functor), m_compiler(compiler) + ClassProbeVisitor(Compiler* compiler, TFunctor& functor) + : GenTreeVisitor(compiler), m_functor(functor), m_compiler(compiler) { } Compiler::fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) { GenTree* const node = *use; - if (node->IsCall() && (m_compiler->compClassifyGDVProbeType(node->AsCall()) != Compiler::GDVProbeType::None)) + if (node->IsCall() && (node->AsCall()->gtClassProfileCandidateInfo != nullptr)) { - assert(node->AsCall()->gtHandleHistogramProfileCandidateInfo != nullptr); - m_functor(m_compiler, node->AsCall()); + GenTreeCall* const call = node->AsCall(); + if (call->IsVirtual() && (call->gtCallType != CT_INDIRECT)) + { + // virtual call + m_functor(m_compiler, call); + } + else if (m_compiler->impIsCastHelperEligibleForClassProbe(call)) + { + // isinst/cast helper + m_functor(m_compiler, call); + } } return Compiler::WALK_CONTINUE; @@ -1458,65 +1467,44 @@ class HandleHistogramProbeVisitor final : public GenTreeVisitorcompClassifyGDVProbeType(call); - - if ((probeType == Compiler::GDVProbeType::ClassProfile) || - (probeType == Compiler::GDVProbeType::MethodAndClassProfile)) - { - CreateHistogramSchemaEntries(compiler, call, true /* isTypeHistogram */); - } - - if ((probeType == Compiler::GDVProbeType::MethodProfile) || - (probeType == Compiler::GDVProbeType::MethodAndClassProfile)) - { - CreateHistogramSchemaEntries(compiler, call, false /* isTypeHistogram */); - } - } - - void CreateHistogramSchemaEntries(Compiler* compiler, GenTreeCall* call, bool isTypeHistogram) - { - ICorJitInfo::PgoInstrumentationSchema schemaElem = {}; - schemaElem.Count = 1; - schemaElem.Other = isTypeHistogram ? ICorJitInfo::HandleHistogram32::CLASS_FLAG : 0; + ICorJitInfo::PgoInstrumentationSchema schemaElem; + schemaElem.Count = 1; + schemaElem.Other = ICorJitInfo::ClassProfile32::CLASS_FLAG; if (call->IsVirtualStub()) { - schemaElem.Other |= ICorJitInfo::HandleHistogram32::INTERFACE_FLAG; + schemaElem.Other |= ICorJitInfo::ClassProfile32::INTERFACE_FLAG; } - else if (call->IsDelegateInvoke()) + else { - schemaElem.Other |= ICorJitInfo::HandleHistogram32::DELEGATE_FLAG; + assert(call->IsVirtualVtable() || compiler->impIsCastHelperEligibleForClassProbe(call)); } schemaElem.InstrumentationKind = JitConfig.JitCollect64BitCounts() ? ICorJitInfo::PgoInstrumentationKind::HandleHistogramLongCount : ICorJitInfo::PgoInstrumentationKind::HandleHistogramIntCount; - schemaElem.ILOffset = (int32_t)call->gtHandleHistogramProfileCandidateInfo->ilOffset; + schemaElem.ILOffset = (int32_t)call->gtClassProfileCandidateInfo->ilOffset; schemaElem.Offset = 0; m_schema.push_back(schemaElem); - m_schemaCount++; - // Re-using ILOffset and Other fields from schema item for TypeHandleHistogramCount - schemaElem.InstrumentationKind = isTypeHistogram ? ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes - : ICorJitInfo::PgoInstrumentationKind::HandleHistogramMethods; - schemaElem.Count = ICorJitInfo::HandleHistogram32::SIZE; + schemaElem.InstrumentationKind = ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes; + schemaElem.Count = ICorJitInfo::ClassProfile32::SIZE; m_schema.push_back(schemaElem); m_schemaCount++; @@ -1524,9 +1512,9 @@ class BuildHandleHistogramProbeSchemaGen }; //------------------------------------------------------------------------ -// HandleHistogramProbeInserter: functor that adds class/method probe instrumentation +// ClassProbeInserter: functor that adds class probe instrumentation // -class HandleHistogramProbeInserter +class ClassProbeInserter { Schema& m_schema; uint8_t* m_profileMemory; @@ -1534,7 +1522,7 @@ class HandleHistogramProbeInserter unsigned& m_instrCount; public: - HandleHistogramProbeInserter(Schema& schema, uint8_t* profileMemory, int* pCurrentSchemaIndex, unsigned& instrCount) + ClassProbeInserter(Schema& schema, uint8_t* profileMemory, int* pCurrentSchemaIndex, unsigned& instrCount) : m_schema(schema) , m_profileMemory(profileMemory) , m_currentSchemaIndex(pCurrentSchemaIndex) @@ -1545,11 +1533,10 @@ class HandleHistogramProbeInserter void operator()(Compiler* compiler, GenTreeCall* call) { JITDUMP("Found call [%06u] with probe index %d and ilOffset 0x%X\n", compiler->dspTreeID(call), - call->gtHandleHistogramProfileCandidateInfo->probeIndex, - call->gtHandleHistogramProfileCandidateInfo->ilOffset); + call->gtClassProfileCandidateInfo->probeIndex, call->gtClassProfileCandidateInfo->ilOffset); // We transform the call from (CALLVIRT obj, ... args ...) to - // + // to // (CALLVIRT // (COMMA // (ASG tmp, obj) @@ -1559,25 +1546,19 @@ class HandleHistogramProbeInserter // ... args ...) // - // Read histograms - void* typeHistogram = nullptr; - void* methodHistogram = nullptr; - - bool is32; - ReadHistogramAndAdvance(call->gtHandleHistogramProfileCandidateInfo->ilOffset, &typeHistogram, &methodHistogram, - &is32); - bool secondIs32; - ReadHistogramAndAdvance(call->gtHandleHistogramProfileCandidateInfo->ilOffset, &typeHistogram, &methodHistogram, - &secondIs32); - - assert(((typeHistogram != nullptr) || (methodHistogram != nullptr)) && - "Expected at least one handle histogram when inserting probes"); - - if ((typeHistogram != nullptr) && (methodHistogram != nullptr)) - { - // We expect both histograms to be 32-bit or 64-bit, not a mix. - assert(is32 == secondIs32); - } + // Sanity check that we're looking at the right schema entry + // + assert(m_schema[*m_currentSchemaIndex].ILOffset == (int32_t)call->gtClassProfileCandidateInfo->ilOffset); + bool is32 = m_schema[*m_currentSchemaIndex].InstrumentationKind == + ICorJitInfo::PgoInstrumentationKind::HandleHistogramIntCount; + bool is64 = m_schema[*m_currentSchemaIndex].InstrumentationKind == + ICorJitInfo::PgoInstrumentationKind::HandleHistogramLongCount; + assert(is32 || is64); + + // Figure out where the table is located. + // + uint8_t* classProfile = m_schema[*m_currentSchemaIndex].Offset + m_profileMemory; + *m_currentSchemaIndex += 2; // There are 2 schema entries per class probe assert(!call->gtArgs.AreArgsComplete()); CallArg* objUse = nullptr; @@ -1595,57 +1576,20 @@ class HandleHistogramProbeInserter // Grab a temp to hold the 'this' object as it will be used three times // - unsigned const tmpNum = compiler->lvaGrabTemp(true DEBUGARG("handle histogram profile tmp")); + unsigned const tmpNum = compiler->lvaGrabTemp(true DEBUGARG("class profile tmp")); compiler->lvaTable[tmpNum].lvType = TYP_REF; - GenTree* helperCallNode = nullptr; - - if (typeHistogram != nullptr) - { - GenTree* const tmpNode = compiler->gtNewLclvNode(tmpNum, TYP_REF); - GenTree* const classProfileNode = compiler->gtNewIconNode((ssize_t)typeHistogram, TYP_I_IMPL); - helperCallNode = - compiler->gtNewHelperCallNode(is32 ? CORINFO_HELP_CLASSPROFILE32 : CORINFO_HELP_CLASSPROFILE64, - TYP_VOID, tmpNode, classProfileNode); - } - - if (methodHistogram != nullptr) - { - GenTree* const tmpNode = compiler->gtNewLclvNode(tmpNum, TYP_REF); - GenTree* const methodProfileNode = compiler->gtNewIconNode((ssize_t)methodHistogram, TYP_I_IMPL); - - GenTree* methodProfileCallNode; - if (call->IsDelegateInvoke()) - { - methodProfileCallNode = compiler->gtNewHelperCallNode(is32 ? CORINFO_HELP_DELEGATEPROFILE32 - : CORINFO_HELP_DELEGATEPROFILE64, - TYP_VOID, tmpNode, methodProfileNode); - } - else - { - assert(call->IsVirtualVtable()); - GenTree* const baseMethodNode = compiler->gtNewIconEmbMethHndNode(call->gtCallMethHnd); - methodProfileCallNode = - compiler->gtNewHelperCallNode(is32 ? CORINFO_HELP_VTABLEPROFILE32 : CORINFO_HELP_VTABLEPROFILE64, - TYP_VOID, tmpNode, baseMethodNode, methodProfileNode); - } - - if (helperCallNode == nullptr) - { - helperCallNode = methodProfileCallNode; - } - else - { - helperCallNode = compiler->gtNewOperNode(GT_COMMA, TYP_REF, helperCallNode, methodProfileCallNode); - } - } - // Generate the IR... // + GenTree* const classProfileNode = compiler->gtNewIconNode((ssize_t)classProfile, TYP_I_IMPL); + GenTree* const tmpNode = compiler->gtNewLclvNode(tmpNum, TYP_REF); + GenTreeCall* const helperCallNode = + compiler->gtNewHelperCallNode(is32 ? CORINFO_HELP_CLASSPROFILE32 : CORINFO_HELP_CLASSPROFILE64, TYP_VOID, + tmpNode, classProfileNode); GenTree* const tmpNode2 = compiler->gtNewLclvNode(tmpNum, TYP_REF); GenTree* const callCommaNode = compiler->gtNewOperNode(GT_COMMA, TYP_REF, helperCallNode, tmpNode2); GenTree* const tmpNode3 = compiler->gtNewLclvNode(tmpNum, TYP_REF); - GenTree* const asgNode = compiler->gtNewOperNode(GT_ASG, TYP_REF, tmpNode3, objUse->GetNode()); + GenTree* const asgNode = compiler->gtNewOperNode(GT_ASG, TYP_REF, tmpNode3, objUse->GetEarlyNode()); GenTree* const asgCommaNode = compiler->gtNewOperNode(GT_COMMA, TYP_REF, asgNode, callCommaNode); // Update the call @@ -1657,78 +1601,16 @@ class HandleHistogramProbeInserter m_instrCount++; } - -private: - void ReadHistogramAndAdvance(IL_OFFSET ilOffset, void** typeHistogram, void** methodHistogram, bool* histogramIs32) - { - if (*m_currentSchemaIndex >= (int)m_schema.size()) - { - return; - } - - ICorJitInfo::PgoInstrumentationSchema& countEntry = m_schema[*m_currentSchemaIndex]; - - bool is32 = countEntry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramIntCount; - bool is64 = countEntry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramLongCount; - if (!is32 && !is64) - { - return; - } - - if (countEntry.ILOffset != static_cast(ilOffset)) - { - return; - } - - assert(*m_currentSchemaIndex + 2 <= (int)m_schema.size()); - ICorJitInfo::PgoInstrumentationSchema& tableEntry = m_schema[*m_currentSchemaIndex + 1]; - assert((tableEntry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes) || - (tableEntry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramMethods)); - - void** outHistogram; - if (tableEntry.InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes) - { - assert(*typeHistogram == nullptr); - outHistogram = typeHistogram; - } - else - { - assert(*methodHistogram == nullptr); - outHistogram = methodHistogram; - } - - *outHistogram = &m_profileMemory[countEntry.Offset]; - *histogramIs32 = is32; - -#ifdef DEBUG - if (is32) - { - ICorJitInfo::HandleHistogram32* h32 = - reinterpret_cast(&m_profileMemory[countEntry.Offset]); - assert(reinterpret_cast(&h32->Count) == &m_profileMemory[countEntry.Offset]); - assert(reinterpret_cast(h32->HandleTable) == &m_profileMemory[tableEntry.Offset]); - } - else - { - ICorJitInfo::HandleHistogram64* h64 = - reinterpret_cast(&m_profileMemory[countEntry.Offset]); - assert(reinterpret_cast(&h64->Count) == &m_profileMemory[countEntry.Offset]); - assert(reinterpret_cast(h64->HandleTable) == &m_profileMemory[tableEntry.Offset]); - } -#endif - - *m_currentSchemaIndex += 2; - } }; //------------------------------------------------------------------------ -// HandleHistogramProbeInstrumentor: instrumentor that adds a class probe to each +// ClassProbeInstrumentor: instrumentor that adds a class probe to each // virtual call in the basic block // -class HandleHistogramProbeInstrumentor : public Instrumentor +class ClassProbeInstrumentor : public Instrumentor { public: - HandleHistogramProbeInstrumentor(Compiler* comp) : Instrumentor(comp) + ClassProbeInstrumentor(Compiler* comp) : Instrumentor(comp) { } bool ShouldProcess(BasicBlock* block) override @@ -1741,13 +1623,13 @@ class HandleHistogramProbeInstrumentor : public Instrumentor }; //------------------------------------------------------------------------ -// HandleHistogramProbeInstrumentor::Prepare: prepare for class instrumentation +// ClassProbeInstrumentor::Prepare: prepare for class instrumentation // // Arguments: // preImport - true if this is the prepare call that happens before // importation // -void HandleHistogramProbeInstrumentor::Prepare(bool isPreImport) +void ClassProbeInstrumentor::Prepare(bool isPreImport) { if (isPreImport) { @@ -1759,33 +1641,33 @@ void HandleHistogramProbeInstrumentor::Prepare(bool isPreImport) // for (BasicBlock* const block : m_comp->Blocks()) { - block->bbHistogramSchemaIndex = -1; + block->bbClassSchemaIndex = -1; } #endif } //------------------------------------------------------------------------ -// HandleHistogramProbeInstrumentor::BuildSchemaElements: create schema elements for a class probe +// ClassProbeInstrumentor::BuildSchemaElements: create schema elements for a class probe // // Arguments: // block -- block to instrument // schema -- schema that we're building // -void HandleHistogramProbeInstrumentor::BuildSchemaElements(BasicBlock* block, Schema& schema) +void ClassProbeInstrumentor::BuildSchemaElements(BasicBlock* block, Schema& schema) { - if ((block->bbFlags & BBF_HAS_HISTOGRAM_PROFILE) == 0) + if ((block->bbFlags & BBF_HAS_CLASS_PROFILE) == 0) { return; } // Remember the schema index for this block. // - block->bbHistogramSchemaIndex = (int)schema.size(); + block->bbClassSchemaIndex = (int)schema.size(); // Scan the statements and identify the class probes // - BuildHandleHistogramProbeSchemaGen schemaGen(schema, m_schemaCount); - HandleHistogramProbeVisitor visitor(m_comp, schemaGen); + BuildClassProbeSchemaGen schemaGen(schema, m_schemaCount); + ClassProbeVisitor visitor(m_comp, schemaGen); for (Statement* const stmt : block->Statements()) { visitor.WalkTree(stmt->GetRootNodePointer(), nullptr); @@ -1793,16 +1675,16 @@ void HandleHistogramProbeInstrumentor::BuildSchemaElements(BasicBlock* block, Sc } //------------------------------------------------------------------------ -// HandleHistogramProbeInstrumentor::Instrument: add class probes to block +// ClassProbeInstrumentor::Instrument: add class probes to block // // Arguments: // block -- block of interest // schema -- instrumentation schema // profileMemory -- profile data slab // -void HandleHistogramProbeInstrumentor::Instrument(BasicBlock* block, Schema& schema, uint8_t* profileMemory) +void ClassProbeInstrumentor::Instrument(BasicBlock* block, Schema& schema, uint8_t* profileMemory) { - if ((block->bbFlags & BBF_HAS_HISTOGRAM_PROFILE) == 0) + if ((block->bbFlags & BBF_HAS_CLASS_PROFILE) == 0) { return; } @@ -1814,11 +1696,11 @@ void HandleHistogramProbeInstrumentor::Instrument(BasicBlock* block, Schema& sch // Scan the statements and add class probes // - int histogramSchemaIndex = block->bbHistogramSchemaIndex; - assert((histogramSchemaIndex >= 0) && (histogramSchemaIndex < (int)schema.size())); + int classSchemaIndex = block->bbClassSchemaIndex; + assert((classSchemaIndex >= 0) && (classSchemaIndex < (int)schema.size())); - HandleHistogramProbeInserter insertProbes(schema, profileMemory, &histogramSchemaIndex, m_instrCount); - HandleHistogramProbeVisitor visitor(m_comp, insertProbes); + ClassProbeInserter insertProbes(schema, profileMemory, &classSchemaIndex, m_instrCount); + ClassProbeVisitor visitor(m_comp, insertProbes); for (Statement* const stmt : block->Statements()) { visitor.WalkTree(stmt->GetRootNodePointer(), nullptr); @@ -1907,25 +1789,24 @@ PhaseStatus Compiler::fgPrepareToInstrumentMethod() // Enable class profiling by default, when jitting. // Todo: we may also want this on by default for prejitting. // - const bool useClassProfiles = (JitConfig.JitClassProfiling() > 0); - const bool useDelegateProfiles = (JitConfig.JitDelegateProfiling() > 0); - const bool useVTableProfiles = (JitConfig.JitVTableProfiling() > 0); - if (!prejit && (useClassProfiles || useDelegateProfiles || useVTableProfiles)) + const bool useClassProfiles = (JitConfig.JitClassProfiling() > 0) && !prejit; + if (useClassProfiles) { - fgHistogramInstrumentor = new (this, CMK_Pgo) HandleHistogramProbeInstrumentor(this); + fgClassInstrumentor = new (this, CMK_Pgo) ClassProbeInstrumentor(this); } else { - JITDUMP("Not doing class/method profiling, because %s\n", prejit ? "prejit" : "class/method profiles disabled"); + JITDUMP("Not doing class profiling, because %s\n", + (JitConfig.JitClassProfiling() > 0) ? "class profiles disabled" : "prejit"); - fgHistogramInstrumentor = new (this, CMK_Pgo) NonInstrumentor(this); + fgClassInstrumentor = new (this, CMK_Pgo) NonInstrumentor(this); } // Make pre-import preparations. // const bool isPreImport = true; fgCountInstrumentor->Prepare(isPreImport); - fgHistogramInstrumentor->Prepare(isPreImport); + fgClassInstrumentor->Prepare(isPreImport); return PhaseStatus::MODIFIED_NOTHING; } @@ -1954,7 +1835,7 @@ PhaseStatus Compiler::fgInstrumentMethod() // const bool isPreImport = false; fgCountInstrumentor->Prepare(isPreImport); - fgHistogramInstrumentor->Prepare(isPreImport); + fgClassInstrumentor->Prepare(isPreImport); // Walk the flow graph to build up the instrumentation schema. // @@ -1966,12 +1847,27 @@ PhaseStatus Compiler::fgInstrumentMethod() fgCountInstrumentor->BuildSchemaElements(block, schema); } - if (fgHistogramInstrumentor->ShouldProcess(block)) + if (fgClassInstrumentor->ShouldProcess(block)) { - fgHistogramInstrumentor->BuildSchemaElements(block, schema); + fgClassInstrumentor->BuildSchemaElements(block, schema); } } + // Verify we created schema for the calls needing class probes. + // (we counted those when importing) + // + // This is not true when we do partial compilation; it can/will erase class probes, + // and there's no easy way to figure out how many should be left. + // + if (doesMethodHavePartialCompilationPatchpoints()) + { + assert(fgClassInstrumentor->SchemaCount() <= info.compClassProbeCount); + } + else + { + assert(fgClassInstrumentor->SchemaCount() == info.compClassProbeCount); + } + // Optionally, when jitting, if there were no class probes and only one count probe, // suppress instrumentation. // @@ -1991,7 +1887,7 @@ PhaseStatus Compiler::fgInstrumentMethod() minimalProbeMode = (JitConfig.JitMinimalJitProfiling() > 0); } - if (minimalProbeMode && (fgCountInstrumentor->SchemaCount() == 1) && (fgHistogramInstrumentor->SchemaCount() == 0)) + if (minimalProbeMode && (fgCountInstrumentor->SchemaCount() == 1) && (fgClassInstrumentor->SchemaCount() == 0)) { JITDUMP( "Not instrumenting method: minimal probing enabled, and method has only one counter and no class probes\n"); @@ -1999,7 +1895,7 @@ PhaseStatus Compiler::fgInstrumentMethod() } JITDUMP("Instrumenting method: %d count probes and %d class probes\n", fgCountInstrumentor->SchemaCount(), - fgHistogramInstrumentor->SchemaCount()); + fgClassInstrumentor->SchemaCount()); assert(schema.size() > 0); @@ -2032,7 +1928,7 @@ PhaseStatus Compiler::fgInstrumentMethod() // Do any cleanup we might need to do... // fgCountInstrumentor->SuppressProbes(); - fgHistogramInstrumentor->SuppressProbes(); + fgClassInstrumentor->SuppressProbes(); // If we needed to create cheap preds, we're done with them now. // @@ -2043,7 +1939,7 @@ PhaseStatus Compiler::fgInstrumentMethod() // We may have modified control flow preparing for instrumentation. // - const bool modifiedFlow = fgCountInstrumentor->ModifiedFlow() || fgHistogramInstrumentor->ModifiedFlow(); + const bool modifiedFlow = fgCountInstrumentor->ModifiedFlow() || fgClassInstrumentor->ModifiedFlow(); return modifiedFlow ? PhaseStatus::MODIFIED_EVERYTHING : PhaseStatus::MODIFIED_NOTHING; } @@ -2058,25 +1954,22 @@ PhaseStatus Compiler::fgInstrumentMethod() fgCountInstrumentor->Instrument(block, schema, profileMemory); } - if (fgHistogramInstrumentor->ShouldProcess(block)) + if (fgClassInstrumentor->ShouldProcess(block)) { - fgHistogramInstrumentor->Instrument(block, schema, profileMemory); + fgClassInstrumentor->Instrument(block, schema, profileMemory); } } // Verify we instrumented everthing we created schemas for. // assert(fgCountInstrumentor->InstrCount() == fgCountInstrumentor->SchemaCount()); - - // Verify we instrumented for each probe - // - assert(fgHistogramInstrumentor->InstrCount() == info.compHandleHistogramProbeCount); + assert(fgClassInstrumentor->InstrCount() == fgClassInstrumentor->SchemaCount()); // Add any special entry instrumentation. This does not // use the schema mechanism. // fgCountInstrumentor->InstrumentMethodEntry(schema, profileMemory); - fgHistogramInstrumentor->InstrumentMethodEntry(schema, profileMemory); + fgClassInstrumentor->InstrumentMethodEntry(schema, profileMemory); // If we needed to create cheap preds, we're done with them now. // @@ -2159,10 +2052,6 @@ PhaseStatus Compiler::fgIncorporateProfileData() fgPgoClassProfiles++; break; - case ICorJitInfo::PgoInstrumentationKind::GetLikelyMethod: - fgPgoMethodProfiles++; - break; - case ICorJitInfo::PgoInstrumentationKind::HandleHistogramIntCount: case ICorJitInfo::PgoInstrumentationKind::HandleHistogramLongCount: if (iSchema + 1 < fgPgoSchemaCount) diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index 33d6fab81e5ae..da1bcd79595aa 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -1528,7 +1528,7 @@ GenTree* Compiler::fgGetCritSectOfStaticMethod() critSect = info.compCompHnd->getMethodSync(info.compMethodHnd, (void**)&pCrit); noway_assert((!critSect) != (!pCrit)); - tree = gtNewIconEmbHndNode(critSect, pCrit, GTF_ICON_GLOBAL_PTR, info.compMethodHnd); + tree = gtNewIconEmbHndNode(critSect, pCrit, GTF_ICON_METHOD_HDL, info.compMethodHnd); } else { @@ -3421,7 +3421,6 @@ PhaseStatus Compiler::fgDetermineFirstColdBlock() { firstColdBlock = fgFirstBB->bbNext; prevToFirstColdBlock = fgFirstBB; - JITDUMP("JitStressProcedureSplitting is enabled: Splitting after the first basic block\n"); } else { @@ -4130,6 +4129,47 @@ void Compiler::fgSetBlockOrder(BasicBlock* block) return firstNode; } +/*static*/ Compiler::fgWalkResult Compiler::fgChkThrowCB(GenTree** pTree, fgWalkData* data) +{ + GenTree* tree = *pTree; + + // If this tree doesn't have the EXCEPT flag set, then there is no + // way any of the child nodes could throw, so we can stop recursing. + if (!(tree->gtFlags & GTF_EXCEPT)) + { + return Compiler::WALK_SKIP_SUBTREES; + } + + switch (tree->gtOper) + { + case GT_MUL: + case GT_ADD: + case GT_SUB: + case GT_CAST: + if (tree->gtOverflow()) + { + return Compiler::WALK_ABORT; + } + break; + + case GT_INDEX_ADDR: + // This calls CORINFO_HELP_RNGCHKFAIL for Debug code. + if (tree->AsIndexAddr()->IsBoundsChecked()) + { + return Compiler::WALK_ABORT; + } + break; + + case GT_BOUNDS_CHECK: + return Compiler::WALK_ABORT; + + default: + break; + } + + return Compiler::WALK_CONTINUE; +} + /*static*/ Compiler::fgWalkResult Compiler::fgChkLocAllocCB(GenTree** pTree, fgWalkData* data) { GenTree* tree = *pTree; diff --git a/src/coreclr/jit/forwardsub.cpp b/src/coreclr/jit/forwardsub.cpp index e6e2c84e80762..4c3fae5f1d9f9 100644 --- a/src/coreclr/jit/forwardsub.cpp +++ b/src/coreclr/jit/forwardsub.cpp @@ -504,6 +504,12 @@ bool Compiler::fgForwardSubStatement(Statement* stmt) return false; } + if (gtGetStructHandleIfPresent(fwdSubNode) != gtGetStructHandleIfPresent(lhsNode)) + { + JITDUMP(" would change struct handle (assignment)\n"); + return false; + } + // If lhs is mulit-reg, rhs must be too. // if (lhsNode->IsMultiRegNode() && !fwdSubNode->IsMultiRegNode()) @@ -659,40 +665,12 @@ bool Compiler::fgForwardSubStatement(Statement* stmt) // Quirks: // - // Don't substitute nodes "AddFinalArgsAndDetermineABIInfo" doesn't handle into struct args. - // - if (fsv.IsCallArg() && fsv.GetNode()->TypeIs(TYP_STRUCT) && - !fwdSubNode->OperIs(GT_OBJ, GT_LCL_VAR, GT_LCL_FLD, GT_MKREFANY)) - { - JITDUMP(" use is a struct arg; fwd sub node is not OBJ/LCL_VAR/LCL_FLD/MKREFANY\n"); - return false; - } - // We may sometimes lose or change a type handle. Avoid substituting if so. // - // However, we allow free substitution of hardware SIMD types. - // - CORINFO_CLASS_HANDLE fwdHnd = gtGetStructHandleIfPresent(fwdSubNode); - CORINFO_CLASS_HANDLE useHnd = gtGetStructHandleIfPresent(fsv.GetNode()); - if (fwdHnd != useHnd) + if (gtGetStructHandleIfPresent(fwdSubNode) != gtGetStructHandleIfPresent(fsv.GetNode())) { - if ((fwdHnd == NO_CLASS_HANDLE) || (useHnd == NO_CLASS_HANDLE)) - { - JITDUMP(" would add/remove struct handle (substitution)\n"); - return false; - } - -#ifdef FEATURE_SIMD - const bool bothHWSIMD = isHWSIMDClass(fwdHnd) && isHWSIMDClass(useHnd); -#else - const bool bothHWSIMD = false; -#endif - - if (!bothHWSIMD) - { - JITDUMP(" would change struct handle (substitution)\n"); - return false; - } + JITDUMP(" would change struct handle (substitution)\n"); + return false; } #ifdef FEATURE_SIMD diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 17842a4195f02..f6a167a50e139 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -567,50 +567,14 @@ void Compiler::fgWalkAllTreesPre(fgWalkPreFn* visitor, void* pCallBackData) } } -//----------------------------------------------------------- -// GetLayout: Get the struct layout for this node. -// -// Arguments: -// compiler - The Compiler instance -// -// Return Value: -// The struct layout of this node; it must have one. -// -// Notes: -// This is the "general" method for getting the layout, -// the more efficient node-specific ones should be used -// in case the node's oper is known. -// -ClassLayout* GenTree::GetLayout(Compiler* compiler) const -{ - assert(varTypeIsStruct(TypeGet())); - - switch (OperGet()) - { - case GT_LCL_VAR: - return compiler->lvaGetDesc(AsLclVar())->GetLayout(); - - case GT_LCL_FLD: - return AsLclFld()->GetLayout(); - - case GT_OBJ: - case GT_BLK: - return AsBlk()->GetLayout(); - - case GT_MKREFANY: - return compiler->typGetObjLayout(compiler->impGetRefAnyClass()); - - default: - unreached(); - } -} - //----------------------------------------------------------- // CopyReg: Copy the _gtRegNum/gtRegTag fields. // // Arguments: // from - GenTree node from which to copy // +// Return Value: +// None void GenTree::CopyReg(GenTree* from) { _gtRegNum = from->_gtRegNum; @@ -2432,8 +2396,7 @@ bool GenTree::Compare(GenTree* op1, GenTree* op2, bool swapOK) case GT_LCL_FLD: if ((op1->AsLclFld()->GetLclNum() != op2->AsLclFld()->GetLclNum()) || - (op1->AsLclFld()->GetLclOffs() != op2->AsLclFld()->GetLclOffs()) || - (op1->AsLclFld()->GetLayout() != op2->AsLclFld()->GetLayout())) + (op1->AsLclFld()->GetLclOffs() != op2->AsLclFld()->GetLclOffs())) { break; } @@ -2829,7 +2792,6 @@ unsigned Compiler::gtHashValue(GenTree* tree) break; case GT_LCL_FLD: hash = genTreeHashAdd(hash, tree->AsLclFld()->GetLclNum()); - hash = genTreeHashAdd(hash, tree->AsLclFld()->GetLayout()); add = tree->AsLclFld()->GetLclOffs(); break; @@ -4437,11 +4399,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) { costSz = 10; costEx = 2; - if (con->IsIconHandle()) - { - // A sort of a hint for CSE to try harder for class handles - costEx += 1; - } } #endif // TARGET_AMD64 else @@ -4683,11 +4640,6 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree) costEx += 1; costSz += 1; } - else if (tree->TypeIs(TYP_STRUCT)) - { - costEx += IND_COST_EX; - costSz += 2; - } break; case GT_LCL_FLD_ADDR: @@ -6354,20 +6306,16 @@ bool GenTree::OperIsImplicitIndir() const } //------------------------------------------------------------------------------ -// OperExceptions : Get exception set this tree may throw. +// OperMayThrow : Check whether the operation may throw. // // // Arguments: // comp - Compiler instance // // Return Value: -// A bit set of exceptions this tree may throw. -// -// Remarks: -// Should not be used on calls given that we can say nothing precise about -// those. -// -ExceptionSetFlags GenTree::OperExceptions(Compiler* comp) +// True if the given operator may cause an exception + +bool GenTree::OperMayThrow(Compiler* comp) { GenTree* op; @@ -6384,40 +6332,26 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp) if (varTypeIsFloating(op->TypeGet())) { - return ExceptionSetFlags::None; + return false; // Floating point division does not throw. } // For integers only division by 0 or by -1 can throw - if (op->IsIntegralConst()) + if (op->IsIntegralConst() && !op->IsIntegralConst(0) && !op->IsIntegralConst(-1)) { - if (op->IsIntegralConst(0)) - { - return ExceptionSetFlags::DivideByZeroException; - } - if (op->IsIntegralConst(-1)) - { - return ExceptionSetFlags::ArithmeticException; - } - - return ExceptionSetFlags::None; + return false; } - - return ExceptionSetFlags::DivideByZeroException | ExceptionSetFlags::ArithmeticException; + return true; case GT_INTRINSIC: // If this is an intrinsic that represents the object.GetType(), it can throw an NullReferenceException. // Currently, this is the only intrinsic that can throw an exception. - if (AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType) - { - return ExceptionSetFlags::NullReferenceException; - } - - return ExceptionSetFlags::None; + return AsIntrinsic()->gtIntrinsicName == NI_System_Object_GetType; case GT_CALL: - assert(!"Unexpected GT_CALL in OperExceptions"); - return ExceptionSetFlags::All; + CorInfoHelpFunc helper; + helper = comp->eeGetHelperNum(this->AsCall()->gtCallMethHnd); + return ((helper == CORINFO_HELP_UNDEF) || !comp->s_helperCallProperties.NoThrow(helper)); case GT_IND: case GT_BLK: @@ -6425,28 +6359,14 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp) case GT_NULLCHECK: case GT_STORE_BLK: case GT_STORE_DYN_BLK: - if (((this->gtFlags & GTF_IND_NONFAULTING) == 0) && comp->fgAddrCouldBeNull(this->AsIndir()->Addr())) - { - return ExceptionSetFlags::NullReferenceException; - } - - return ExceptionSetFlags::None; + return (((this->gtFlags & GTF_IND_NONFAULTING) == 0) && comp->fgAddrCouldBeNull(this->AsIndir()->Addr())); case GT_ARR_LENGTH: - if (((this->gtFlags & GTF_IND_NONFAULTING) == 0) && comp->fgAddrCouldBeNull(this->AsArrLen()->ArrRef())) - { - return ExceptionSetFlags::NullReferenceException; - } - - return ExceptionSetFlags::None; + return (((this->gtFlags & GTF_IND_NONFAULTING) == 0) && + comp->fgAddrCouldBeNull(this->AsArrLen()->ArrRef())); case GT_ARR_ELEM: - if (comp->fgAddrCouldBeNull(this->AsArrElem()->gtArrObj)) - { - return ExceptionSetFlags::NullReferenceException; - } - - return ExceptionSetFlags::None; + return comp->fgAddrCouldBeNull(this->AsArrElem()->gtArrObj); case GT_FIELD: { @@ -6454,28 +6374,19 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp) if (fldObj != nullptr) { - if (comp->fgAddrCouldBeNull(fldObj)) - { - return ExceptionSetFlags::NullReferenceException; - } + return comp->fgAddrCouldBeNull(fldObj); } - return ExceptionSetFlags::None; + return false; } case GT_BOUNDS_CHECK: - case GT_INDEX_ADDR: - return ExceptionSetFlags::IndexOutOfRangeException; - case GT_ARR_INDEX: case GT_ARR_OFFSET: - return ExceptionSetFlags::NullReferenceException; - - case GT_CKFINITE: - return ExceptionSetFlags::ArithmeticException; - case GT_LCLHEAP: - return ExceptionSetFlags::StackOverflowException; + case GT_CKFINITE: + case GT_INDEX_ADDR: + return true; #ifdef FEATURE_HW_INTRINSICS case GT_HWINTRINSIC: @@ -6487,42 +6398,23 @@ ExceptionSetFlags GenTree::OperExceptions(Compiler* comp) // This operation contains an implicit indirection // it could throw a null reference exception. // - return ExceptionSetFlags::NullReferenceException; + return true; } - - return ExceptionSetFlags::None; + break; } #endif // FEATURE_HW_INTRINSICS default: - if (gtOverflowEx()) - { - return ExceptionSetFlags::OverflowException; - } - - return ExceptionSetFlags::None; + break; } -} -//------------------------------------------------------------------------------ -// OperMayThrow : Check whether the operation may throw. -// -// -// Arguments: -// comp - Compiler instance -// -// Return Value: -// True if the given operator may cause an exception -// -bool GenTree::OperMayThrow(Compiler* comp) -{ - if (OperIs(GT_CALL)) + /* Overflow arithmetic operations also throw exceptions */ + + if (gtOverflowEx()) { - CorInfoHelpFunc helper; - helper = comp->eeGetHelperNum(this->AsCall()->gtCallMethHnd); - return ((helper == CORINFO_HELP_UNDEF) || !comp->s_helperCallProperties.NoThrow(helper)); + return true; } - return OperExceptions(comp) != ExceptionSetFlags::None; + return false; } //----------------------------------------------------------------------------------- @@ -6853,8 +6745,8 @@ GenTree* Compiler::gtNewIndOfIconHandleNode(var_types indType, size_t addr, GenT GenTree* Compiler::gtNewIconEmbHndNode(void* value, void* pValue, GenTreeFlags iconFlags, void* compileTimeHandle) { - GenTreeIntCon* iconNode; - GenTree* handleNode; + GenTree* iconNode; + GenTree* handleNode; if (value != nullptr) { @@ -6887,13 +6779,7 @@ GenTree* Compiler::gtNewIconEmbHndNode(void* value, void* pValue, GenTreeFlags i handleNode->gtFlags |= GTF_IND_INVARIANT; } - iconNode->gtCompileTimeHandle = (size_t)compileTimeHandle; -#ifdef DEBUG - if (iconFlags == GTF_ICON_FTN_ADDR) - { - iconNode->gtTargetHandle = (size_t)compileTimeHandle; - } -#endif + iconNode->AsIntCon()->gtCompileTimeHandle = (size_t)compileTimeHandle; return handleNode; } @@ -6933,10 +6819,8 @@ GenTree* Compiler::gtNewStringLiteralNode(InfoAccessType iat, void* pValue) tree = gtNewOperNode(GT_IND, TYP_REF, tree); // This indirection won't cause an exception. tree->gtFlags |= GTF_IND_NONFAULTING; - // String literal objects are also ok to model as invariant. - tree->gtFlags |= GTF_IND_INVARIANT; - // ..and they are never null. - tree->gtFlags |= GTF_IND_NONNULL; + // This indirection points into the gloabal heap (it is String Object) + tree->gtFlags |= GTF_GLOB_REF; break; default: @@ -9226,10 +9110,7 @@ GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node) m_state = -1; return; -// Standard unary operators -#ifdef TARGET_ARM64 - case GT_CNEG_LT: -#endif // TARGET_ARM64 + // Standard unary operators case GT_STORE_LCL_VAR: case GT_STORE_LCL_FLD: case GT_NOT: @@ -16176,7 +16057,7 @@ bool Compiler::gtIsTypeHandleToRuntimeTypeHelper(GenTreeCall* call) // // Return Value: // True if so -// + bool Compiler::gtIsTypeHandleToRuntimeTypeHandleHelper(GenTreeCall* call, CorInfoHelpFunc* pHelper) { CorInfoHelpFunc helper = CORINFO_HELP_UNDEF; @@ -16203,61 +16084,6 @@ bool Compiler::gtIsActiveCSE_Candidate(GenTree* tree) return (optValnumCSE_phase && IS_CSE_INDEX(tree->gtCSEnum)); } -//------------------------------------------------------------------------ -// gtCollectExceptions: walk a tree collecting a bit set of exceptions the tree -// may throw. -// -// Arguments: -// tree - tree to examine -// -// Return Value: -// Bit set of exceptions the tree may throw. -// -ExceptionSetFlags Compiler::gtCollectExceptions(GenTree* tree) -{ - class ExceptionsWalker final : public GenTreeVisitor - { - ExceptionSetFlags m_preciseExceptions = ExceptionSetFlags::None; - - public: - ExceptionsWalker(Compiler* comp) : GenTreeVisitor(comp) - { - } - - enum - { - DoPreOrder = true, - }; - - ExceptionSetFlags GetFlags() - { - return m_preciseExceptions; - } - - fgWalkResult PreOrderVisit(GenTree** use, GenTree* user) - { - GenTree* tree = *use; - if ((tree->gtFlags & GTF_EXCEPT) == 0) - { - return WALK_SKIP_SUBTREES; - } - - m_preciseExceptions |= tree->OperExceptions(m_compiler); - return WALK_CONTINUE; - } - }; - - // We only expect the caller to ask for precise exceptions for cases where - // it may help with disambiguating between exceptions. If the tree contains - // a call it can always throw arbitrary exceptions. - assert((tree->gtFlags & GTF_CALL) == 0); - - ExceptionsWalker walker(this); - walker.WalkTree(&tree, nullptr); - assert(((tree->gtFlags & GTF_EXCEPT) == 0) || (walker.GetFlags() != ExceptionSetFlags::None)); - return walker.GetFlags(); -} - /*****************************************************************************/ struct ComplexityStruct @@ -16576,7 +16402,7 @@ const GenTreeLclVarCommon* GenTree::IsLocalAddrExpr() const // GenTreeLclVar* GenTree::IsImplicitByrefParameterValue(Compiler* compiler) { -#if FEATURE_IMPLICIT_BYREFS && !defined(TARGET_LOONGARCH64) // TODO-LOONGARCH64-CQ: enable this. +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) GenTreeLclVar* lcl = nullptr; @@ -16608,7 +16434,7 @@ GenTreeLclVar* GenTree::IsImplicitByrefParameterValue(Compiler* compiler) return lcl; } -#endif // FEATURE_IMPLICIT_BYREFS && !defined(TARGET_LOONGARCH64) +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) return nullptr; } @@ -17368,11 +17194,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree) } #endif } - else #endif - { - structHnd = tree->AsLclFld()->GetLayout()->GetClassHandle(); - } break; case GT_LCL_VAR: { @@ -18580,16 +18402,14 @@ var_types GenTreeJitIntrinsic::GetSimdBaseType() const return JitType2PreciseVarType(simdBaseJitType); } -//------------------------------------------------------------------------ -// OperIsMemoryLoad: Does this SIMD intrinsic have memory load semantics? -// -// Return Value: -// Whether this intrinsic may throw NullReferenceException if the -// address is "null". -// +// Returns true for the SIMD Intrinsic instructions that have MemoryLoad semantics, false otherwise bool GenTreeSIMD::OperIsMemoryLoad() const { - return GetSIMDIntrinsicId() == SIMDIntrinsicInitArray; + if (GetSIMDIntrinsicId() == SIMDIntrinsicInitArray) + { + return true; + } + return false; } // TODO-Review: why are layouts not compared here? @@ -22588,56 +22408,26 @@ GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode( /* isSimdAsHWIntrinsic */ false, op1, op2, op3); } -//------------------------------------------------------------------------ -// OperIsMemoryLoad: Does this HWI node have memory load semantics? -// -// Arguments: -// pAddr - optional [out] parameter for the address -// -// Return Value: -// Whether this intrinsic may throw NullReferenceException if the -// address is "null". -// -bool GenTreeHWIntrinsic::OperIsMemoryLoad(GenTree** pAddr) const +// Returns true for the HW Intrinsic instructions that have MemoryLoad semantics, false otherwise +bool GenTreeHWIntrinsic::OperIsMemoryLoad() const { - GenTree* addr = nullptr; - #if defined(TARGET_XARCH) || defined(TARGET_ARM64) NamedIntrinsic intrinsicId = GetHWIntrinsicId(); HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); if (category == HW_Category_MemoryLoad) { - switch (intrinsicId) - { -#ifdef TARGET_XARCH - case NI_SSE_LoadLow: - case NI_SSE_LoadHigh: - case NI_SSE2_LoadLow: - case NI_SSE2_LoadHigh: - addr = Op(2); - break; -#endif // TARGET_XARCH - -#ifdef TARGET_ARM64 - case NI_AdvSimd_LoadAndInsertScalar: - addr = Op(3); - break; -#endif // TARGET_ARM64 - - default: - addr = Op(1); - break; - } + return true; } #ifdef TARGET_XARCH - else if (HWIntrinsicInfo::MaybeMemoryLoad(intrinsicId)) + else if (HWIntrinsicInfo::MaybeMemoryLoad(GetHWIntrinsicId())) { // Some intrinsics (without HW_Category_MemoryLoad) also have MemoryLoad semantics // This is generally because they have both vector and pointer overloads, e.g., // * Vector128 BroadcastScalarToVector128(Vector128 value) // * Vector128 BroadcastScalarToVector128(byte* source) - // + // So, we need to check the argument's type is memory-reference or Vector128 + if ((category == HW_Category_SimpleSIMD) || (category == HW_Category_SIMDScalar)) { assert(GetOperandCount() == 1); @@ -22652,91 +22442,53 @@ bool GenTreeHWIntrinsic::OperIsMemoryLoad(GenTree** pAddr) const case NI_AVX2_ConvertToVector256Int16: case NI_AVX2_ConvertToVector256Int32: case NI_AVX2_ConvertToVector256Int64: - if (GetAuxiliaryJitType() == CORINFO_TYPE_PTR) - { - addr = Op(1); - } - else + { + CorInfoType auxiliaryType = GetAuxiliaryJitType(); + + if (auxiliaryType == CORINFO_TYPE_PTR) { - assert(GetAuxiliaryJitType() == CORINFO_TYPE_UNDEF); + return true; } - break; + + assert(auxiliaryType == CORINFO_TYPE_UNDEF); + return false; + } default: + { unreached(); + } } } else if (category == HW_Category_IMM) { - switch (intrinsicId) + // Do we have less than 3 operands? + if (GetOperandCount() < 3) { - case NI_AVX2_GatherVector128: - case NI_AVX2_GatherVector256: - addr = Op(1); - break; - - case NI_AVX2_GatherMaskVector128: - case NI_AVX2_GatherMaskVector256: - addr = Op(2); - break; - - default: - break; + return false; + } + else if (HWIntrinsicInfo::isAVX2GatherIntrinsic(GetHWIntrinsicId())) + { + return true; } } } #endif // TARGET_XARCH #endif // TARGET_XARCH || TARGET_ARM64 - - if (pAddr != nullptr) - { - *pAddr = addr; - } - - if (addr != nullptr) - { - assert(varTypeIsI(addr)); - return true; - } - return false; } -//------------------------------------------------------------------------ -// OperIsMemoryLoad: Does this HWI node have memory store semantics? -// -// Arguments: -// pAddr - optional [out] parameter for the address -// -// Return Value: -// Whether this intrinsic may mutate heap state and/or throw a -// NullReferenceException if the address is "null". -// -bool GenTreeHWIntrinsic::OperIsMemoryStore(GenTree** pAddr) const +// Returns true for the HW Intrinsic instructions that have MemoryStore semantics, false otherwise +bool GenTreeHWIntrinsic::OperIsMemoryStore() const { - GenTree* addr = nullptr; - #if defined(TARGET_XARCH) || defined(TARGET_ARM64) - NamedIntrinsic intrinsicId = GetHWIntrinsicId(); - HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(intrinsicId); - + HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(GetHWIntrinsicId()); if (category == HW_Category_MemoryStore) { - switch (intrinsicId) - { -#ifdef TARGET_XARCH - case NI_SSE2_MaskMove: - addr = Op(3); - break; -#endif // TARGET_XARCH - - default: - addr = Op(1); - break; - } + return true; } #ifdef TARGET_XARCH - else if (HWIntrinsicInfo::MaybeMemoryStore(intrinsicId) && + else if (HWIntrinsicInfo::MaybeMemoryStore(GetHWIntrinsicId()) && (category == HW_Category_IMM || category == HW_Category_Scalar)) { // Some intrinsics (without HW_Category_MemoryStore) also have MemoryStore semantics @@ -22747,44 +22499,29 @@ bool GenTreeHWIntrinsic::OperIsMemoryStore(GenTree** pAddr) const // So, the 3-argument form is MemoryStore if (GetOperandCount() == 3) { - switch (intrinsicId) + switch (GetHWIntrinsicId()) { case NI_BMI2_MultiplyNoFlags: case NI_BMI2_X64_MultiplyNoFlags: - addr = Op(3); - break; - + return true; default: - break; + return false; } } } #endif // TARGET_XARCH #endif // TARGET_XARCH || TARGET_ARM64 - - if (pAddr != nullptr) - { - *pAddr = addr; - } - - if (addr != nullptr) - { - assert(varTypeIsI(addr)); - return true; - } - return false; } -//------------------------------------------------------------------------ -// OperIsMemoryLoadOrStore: Does this HWI node have memory load or store semantics? -// -// Return Value: -// Whether "this" is "OperIsMemoryLoad" or "OperIsMemoryStore". -// +// Returns true for the HW Intrinsic instructions that have MemoryLoad or MemoryStore semantics, false otherwise bool GenTreeHWIntrinsic::OperIsMemoryLoadOrStore() const { +#if defined(TARGET_XARCH) || defined(TARGET_ARM64) return OperIsMemoryLoad() || OperIsMemoryStore(); +#else + return false; +#endif } NamedIntrinsic GenTreeHWIntrinsic::GetHWIntrinsicId() const @@ -23385,7 +23122,7 @@ unsigned GenTreeHWIntrinsic::GetResultOpNumForFMA(GenTree* use, GenTree* op1, Ge unsigned GenTreeLclFld::GetSize() const { - return TypeIs(TYP_STRUCT) ? GetLayout()->GetSize() : genTypeSize(TypeGet()); + return genTypeSize(TypeGet()); } #ifdef TARGET_ARM diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index afd71a684725b..b9ba82532a554 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -130,45 +130,6 @@ enum gtCallTypes : BYTE CT_COUNT // fake entry (must be last) }; -enum class ExceptionSetFlags : uint32_t -{ - None = 0x0, - OverflowException = 0x1, - DivideByZeroException = 0x2, - ArithmeticException = 0x4, - NullReferenceException = 0x8, - IndexOutOfRangeException = 0x10, - StackOverflowException = 0x20, - - All = OverflowException | DivideByZeroException | ArithmeticException | NullReferenceException | - IndexOutOfRangeException | StackOverflowException, -}; - -inline constexpr ExceptionSetFlags operator~(ExceptionSetFlags a) -{ - return (ExceptionSetFlags)(~(uint32_t)a); -} - -inline constexpr ExceptionSetFlags operator|(ExceptionSetFlags a, ExceptionSetFlags b) -{ - return (ExceptionSetFlags)((uint32_t)a | (uint32_t)b); -} - -inline constexpr ExceptionSetFlags operator&(ExceptionSetFlags a, ExceptionSetFlags b) -{ - return (ExceptionSetFlags)((uint32_t)a & (uint32_t)b); -} - -inline ExceptionSetFlags& operator|=(ExceptionSetFlags& a, ExceptionSetFlags b) -{ - return a = (ExceptionSetFlags)((uint32_t)a | (uint32_t)b); -} - -inline ExceptionSetFlags& operator&=(ExceptionSetFlags& a, ExceptionSetFlags b) -{ - return a = (ExceptionSetFlags)((uint32_t)a & (uint32_t)b); -} - #ifdef DEBUG /***************************************************************************** * @@ -189,7 +150,7 @@ struct BasicBlock; enum BasicBlockFlags : unsigned __int64; struct InlineCandidateInfo; struct GuardedDevirtualizationCandidateInfo; -struct HandleHistogramProfileCandidateInfo; +struct ClassProfileCandidateInfo; struct LateDevirtualizationInfo; typedef unsigned short AssertionIndex; @@ -447,12 +408,7 @@ enum GenTreeFlags : unsigned int GTF_NOREG_AT_USE = 0x00000100, // tree node is in memory at the point of use GTF_SET_FLAGS = 0x00000200, // Requires that codegen for this node set the flags. Use gtSetFlags() to check this flag. - -#ifdef TARGET_XARCH - GTF_DONT_EXTEND = 0x00000400, // This small-typed tree produces a value with undefined upper bits. Used on x86/x64 as a - // lowering optimization and tells the codegen to use instructions like "mov al, [addr]" - // instead of "movzx/movsx", when the user node doesn't need the upper bits. -#endif // TARGET_XARCH + GTF_USE_FLAGS = 0x00000400, // Indicates that this node uses the flags bits. GTF_MAKE_CSE = 0x00000800, // Hoisted expression: try hard to make this into CSE (see optPerformHoistExpr) GTF_DONT_CSE = 0x00001000, // Don't bother CSE'ing this expr @@ -570,9 +526,16 @@ enum GenTreeFlags : unsigned int // alignment of 1 byte) GTF_IND_INVARIANT = 0x01000000, // GT_IND -- the target is invariant (a prejit indirection) GTF_IND_NONNULL = 0x00400000, // GT_IND -- the indirection never returns null (zero) +#if defined(TARGET_XARCH) + GTF_IND_DONT_EXTEND = 0x00200000, // GT_IND -- the indirection does not need to extend for small types +#endif // TARGET_XARCH GTF_IND_FLAGS = GTF_IND_VOLATILE | GTF_IND_NONFAULTING | GTF_IND_TLS_REF | GTF_IND_UNALIGNED | GTF_IND_INVARIANT | - GTF_IND_NONNULL | GTF_IND_TGT_NOT_HEAP | GTF_IND_TGT_HEAP, + GTF_IND_NONNULL | GTF_IND_TGT_NOT_HEAP | GTF_IND_TGT_HEAP +#if defined(TARGET_XARCH) + | GTF_IND_DONT_EXTEND +#endif // TARGET_XARCH + , GTF_ADDRMODE_NO_CSE = 0x80000000, // GT_ADD/GT_MUL/GT_LSH -- Do not CSE this node only, forms complex // addressing mode @@ -642,6 +605,11 @@ enum GenTreeFlags : unsigned int GTF_SIMDASHW_OP = 0x80000000, // GT_HWINTRINSIC -- Indicates that the structHandle should be gotten from gtGetStructHandleForSIMD // rather than from gtGetStructHandleForHWSIMD. + + // Flag used by assertion prop to indicate that a type is a TYP_LONG +#ifdef TARGET_64BIT + GTF_ASSERTION_PROP_LONG = 0x00000001, +#endif // TARGET_64BIT }; inline constexpr GenTreeFlags operator ~(GenTreeFlags a) @@ -796,8 +764,6 @@ struct GenTree return gtType; } - ClassLayout* GetLayout(Compiler* compiler) const; - #ifdef DEBUG genTreeOps gtOperSave; // Only used to save gtOper when we destroy a node, to aid debugging. #endif @@ -1143,11 +1109,6 @@ struct GenTree return true; } - bool IsNotGcDef() const - { - return IsIntegralConst(0) || IsLocalAddrExpr(); - } - // LIR flags // These helper methods, along with the flag values they manipulate, are defined in lir.h // @@ -1854,7 +1815,6 @@ struct GenTree bool OperRequiresCallFlag(Compiler* comp); bool OperMayThrow(Compiler* comp); - ExceptionSetFlags OperExceptions(Compiler* comp); unsigned GetScaleIndexMul(); unsigned GetScaleIndexShf(); @@ -2050,25 +2010,6 @@ struct GenTree gtFlags &= ~GTF_REVERSE_OPS; } -#if defined(TARGET_XARCH) - void SetDontExtend() - { - assert(varTypeIsSmall(TypeGet()) && OperIs(GT_IND, GT_LCL_FLD)); - gtFlags |= GTF_DONT_EXTEND; - } - - void ClearDontExtend() - { - gtFlags &= ~GTF_DONT_EXTEND; - } - - bool DontExtend() const - { - assert(varTypeIsSmall(TypeGet()) || ((gtFlags & GTF_DONT_EXTEND) == 0)); - return (gtFlags & GTF_DONT_EXTEND) != 0; - } -#endif // TARGET_XARCH - bool IsUnsigned() const { return ((gtFlags & GTF_UNSIGNED) != 0); @@ -3115,7 +3056,8 @@ struct GenTreeIntCon : public GenTreeIntConCommon FieldSeqNode* gtFieldSeq; #ifdef DEBUG - // If the value represents target address (for a field or call), holds the handle of the field (or call). + // If the value represents target address, holds the method handle to that target which is used + // to fetch target method name and display in the disassembled code. size_t gtTargetHandle = 0; #endif @@ -3735,10 +3677,9 @@ struct GenTreeLclFld : public GenTreeLclVarCommon public: GenTreeLclFld(genTreeOps oper, var_types type, unsigned lclNum, unsigned lclOffs, ClassLayout* layout = nullptr) - : GenTreeLclVarCommon(oper, type, lclNum), m_lclOffs(static_cast(lclOffs)) + : GenTreeLclVarCommon(oper, type, lclNum), m_lclOffs(static_cast(lclOffs)), m_layout(layout) { assert(lclOffs <= UINT16_MAX); - SetLayout(layout); } uint16_t GetLclOffs() const @@ -3754,7 +3695,6 @@ struct GenTreeLclFld : public GenTreeLclVarCommon ClassLayout* GetLayout() const { - assert(!TypeIs(TYP_STRUCT) || (m_layout != nullptr)); return m_layout; } @@ -4623,7 +4563,6 @@ class CallArgs void RemovedWellKnownArg(WellKnownArg arg); regNumber GetCustomRegister(Compiler* comp, CorInfoCallConvExtension cc, WellKnownArg arg); void SplitArg(CallArg* arg, unsigned numRegs, unsigned numSlots); - void SortArgs(Compiler* comp, GenTreeCall* call, CallArg** sortedArgs); public: CallArgs(); @@ -4668,6 +4607,7 @@ class CallArgs void AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call); void ArgsComplete(Compiler* comp, GenTreeCall* call); + void SortArgs(Compiler* comp, GenTreeCall* call, CallArg** sortedArgs); void EvalArgsToTemps(Compiler* comp, GenTreeCall* call); void SetNeedsTemp(CallArg* arg); bool IsNonStandard(Compiler* comp, GenTreeCall* call, CallArg* arg); @@ -5368,7 +5308,7 @@ struct GenTreeCall final : public GenTree #if defined(TARGET_ARMARCH) // For ARM architectures, we always use an indirection cell for R2R calls. - if (IsR2RRelativeIndir() && !IsDelegateInvoke()) + if (IsR2RRelativeIndir()) { return WellKnownArg::R2RIndirectionCell; } @@ -5431,7 +5371,7 @@ struct GenTreeCall final : public GenTree // gtInlineCandidateInfo is only used when inlining methods InlineCandidateInfo* gtInlineCandidateInfo; GuardedDevirtualizationCandidateInfo* gtGuardedDevirtualizationCandidateInfo; - HandleHistogramProfileCandidateInfo* gtHandleHistogramProfileCandidateInfo; + ClassProfileCandidateInfo* gtClassProfileCandidateInfo; LateDevirtualizationInfo* gtLateDevirtualizationInfo; CORINFO_GENERIC_HANDLE compileTimeHelperArgumentHandle; // Used to track type handle argument of dynamic helpers void* gtDirectCallAddress; // Used to pass direct call address between lower and codegen @@ -6129,7 +6069,8 @@ struct GenTreeSIMD : public GenTreeJitIntrinsic } #endif - bool OperIsMemoryLoad() const; + bool OperIsMemoryLoad() const; // Returns true for the SIMD Intrinsic instructions that have MemoryLoad semantics, + // false otherwise SIMDIntrinsicID GetSIMDIntrinsicId() const { @@ -6173,10 +6114,12 @@ struct GenTreeHWIntrinsic : public GenTreeJitIntrinsic } #endif - bool OperIsMemoryLoad(GenTree** pAddr = nullptr) const; - bool OperIsMemoryStore(GenTree** pAddr = nullptr) const; - bool OperIsMemoryLoadOrStore() const; - + bool OperIsMemoryLoad() const; // Returns true for the HW Intrinsic instructions that have MemoryLoad semantics, + // false otherwise + bool OperIsMemoryStore() const; // Returns true for the HW Intrinsic instructions that have MemoryStore semantics, + // false otherwise + bool OperIsMemoryLoadOrStore() const; // Returns true for the HW Intrinsic instructions that have MemoryLoad or + // MemoryStore semantics, false otherwise bool IsSimdAsHWIntrinsic() const { return (gtFlags & GTF_SIMDASHW_OP) != 0; @@ -6821,6 +6764,23 @@ struct GenTreeIndir : public GenTreeOp return (gtFlags & GTF_IND_UNALIGNED) != 0; } +#if defined(TARGET_XARCH) + void SetDontExtend() + { + gtFlags |= GTF_IND_DONT_EXTEND; + } + + void ClearDontExtend() + { + gtFlags &= ~GTF_IND_DONT_EXTEND; + } + + bool DontExtend() const + { + return (gtFlags & GTF_IND_DONT_EXTEND) != 0; + } +#endif // TARGET_XARCH + #if DEBUGGABLE_GENTREE // Used only for GenTree::GetVtableForOper() GenTreeIndir() : GenTreeOp() @@ -7481,18 +7441,12 @@ struct GenTreePutArgStk : public GenTreeUnOp // TODO-Throughput: The following information should be obtained from the child // block node. - enum class Kind : int8_t{ + enum class Kind : __int8{ Invalid, RepInstr, PartialRepInstr, Unroll, Push, }; Kind gtPutArgStkKind; +#endif -#ifdef TARGET_XARCH -private: - uint8_t m_argLoadSizeDelta; -#endif // TARGET_XARCH -#endif // FEATURE_PUT_STRUCT_ARG_STK - -public: GenTreePutArgStk(genTreeOps oper, var_types type, GenTree* op1, @@ -7518,10 +7472,7 @@ struct GenTreePutArgStk : public GenTreeUnOp #endif // FEATURE_FASTTAILCALL #if defined(FEATURE_PUT_STRUCT_ARG_STK) , gtPutArgStkKind(Kind::Invalid) -#if defined(TARGET_XARCH) - , m_argLoadSizeDelta(UINT8_MAX) #endif -#endif // FEATURE_PUT_STRUCT_ARG_STK { } @@ -7568,36 +7519,6 @@ struct GenTreePutArgStk : public GenTreeUnOp return m_byteSize; } -#ifdef TARGET_XARCH - //------------------------------------------------------------------------ - // SetArgLoadSize: Set the optimal number of bytes to load for this argument. - // - // On XARCH, it is profitable to use wider loads when our source is a local - // variable. To not duplicate the logic between lowering, LSRA and codegen, - // we do the legality check once, in lowering, and save the result here, as - // a negative delta relative to the size of the argument with padding. - // - // Arguments: - // loadSize - The optimal number of bytes to load - // - void SetArgLoadSize(unsigned loadSize) - { - unsigned argSize = GetStackByteSize(); - assert(roundUp(loadSize, TARGET_POINTER_SIZE) == argSize); - - m_argLoadSizeDelta = static_cast(argSize - loadSize); - } - - //------------------------------------------------------------------------ - // GetArgLoadSize: Get the optimal number of bytes to load for this argument. - // - unsigned GetArgLoadSize() const - { - assert(m_argLoadSizeDelta != UINT8_MAX); - return GetStackByteSize() - m_argLoadSizeDelta; - } -#endif // TARGET_XARCH - // Return true if this is a PutArgStk of a SIMD12 struct. // This is needed because such values are re-typed to SIMD16, and the type of PutArgStk is VOID. unsigned isSIMD12() const diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 53a3618100b9e..a089124825ff9 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -219,7 +219,6 @@ GTNODE(AND_NOT , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) GTNODE(ADDEX, GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Add with sign/zero extension. GTNODE(BFIZ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero. GTNODE(CSNEG_MI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Conditional select, negate, minus result -GTNODE(CNEG_LT , GenTreeOp ,0,GTK_UNOP|DBK_NOTHIR) // Conditional, negate, signed less than result #endif //----------------------------------------------------------------------------- diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 6ad3ef37cf8f1..0885892bcd630 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -314,35 +314,20 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, return NI_Throw_PlatformNotSupportedException; } - // Special case: For Vector64/128/256 we currently don't accelerate any of the methods when - // IsHardwareAccelerated reports false. For Vector64 and Vector128 this is when the baseline - // ISA is unsupported. For Vector256 this is when AVX2 is unsupported since integer types - // can't get properly accelerated. - - if (isa == InstructionSet_Vector128) - { - if (!comp->IsBaselineSimdIsaSupported()) - { - return NI_Illegal; - } - } #if defined(TARGET_XARCH) - else if (isa == InstructionSet_Vector256) - { - if (!comp->compOpportunisticallyDependsOn(InstructionSet_AVX2)) - { - return NI_Illegal; - } - } + if ((isa == InstructionSet_Vector128) || (isa == InstructionSet_Vector256)) #elif defined(TARGET_ARM64) - else if (isa == InstructionSet_Vector64) + if ((isa == InstructionSet_Vector64) || (isa == InstructionSet_Vector128)) +#endif { if (!comp->IsBaselineSimdIsaSupported()) { + // Special case: For Vector64/128/256 we currently don't accelerate any of the methods when SSE/SSE2 + // aren't supported since IsHardwareAccelerated reports false. To simplify the importation logic we'll + // just return illegal here and let it fallback to the software path instead. return NI_Illegal; } } -#endif for (int i = 0; i < (NI_HW_INTRINSIC_END - NI_HW_INTRINSIC_START - 1); i++) { @@ -655,15 +640,48 @@ static bool isSupportedBaseType(NamedIntrinsic intrinsic, CorInfoType baseJitTyp return true; } -#ifdef DEBUG - CORINFO_InstructionSet isa = HWIntrinsicInfo::lookupIsa(intrinsic); #ifdef TARGET_XARCH - assert((isa == InstructionSet_Vector256) || (isa == InstructionSet_Vector128)); + assert((intrinsic == NI_Vector128_As) || (intrinsic == NI_Vector128_AsByte) || + (intrinsic == NI_Vector128_AsDouble) || (intrinsic == NI_Vector128_AsInt16) || + (intrinsic == NI_Vector128_AsInt32) || (intrinsic == NI_Vector128_AsInt64) || + (intrinsic == NI_Vector128_AsSByte) || (intrinsic == NI_Vector128_AsSingle) || + (intrinsic == NI_Vector128_AsUInt16) || (intrinsic == NI_Vector128_AsUInt32) || + (intrinsic == NI_Vector128_AsUInt64) || (intrinsic == NI_Vector128_get_AllBitsSet) || + (intrinsic == NI_Vector128_get_Count) || (intrinsic == NI_Vector128_get_Zero) || + (intrinsic == NI_Vector128_GetElement) || (intrinsic == NI_Vector128_WithElement) || + (intrinsic == NI_Vector128_ToScalar) || (intrinsic == NI_Vector128_ToVector256) || + (intrinsic == NI_Vector128_ToVector256Unsafe) || (intrinsic == NI_Vector256_As) || + (intrinsic == NI_Vector256_AsByte) || (intrinsic == NI_Vector256_AsDouble) || + (intrinsic == NI_Vector256_AsInt16) || (intrinsic == NI_Vector256_AsInt32) || + (intrinsic == NI_Vector256_AsInt64) || (intrinsic == NI_Vector256_AsSByte) || + (intrinsic == NI_Vector256_AsSingle) || (intrinsic == NI_Vector256_AsUInt16) || + (intrinsic == NI_Vector256_AsUInt32) || (intrinsic == NI_Vector256_AsUInt64) || + (intrinsic == NI_Vector256_get_AllBitsSet) || (intrinsic == NI_Vector256_get_Count) || + (intrinsic == NI_Vector256_get_Zero) || (intrinsic == NI_Vector256_GetElement) || + (intrinsic == NI_Vector256_WithElement) || (intrinsic == NI_Vector256_GetLower) || + (intrinsic == NI_Vector256_ToScalar)); #endif // TARGET_XARCH #ifdef TARGET_ARM64 - assert((isa == InstructionSet_Vector64) || (isa == InstructionSet_Vector128)); + assert((intrinsic == NI_Vector64_As) || (intrinsic == NI_Vector64_AsByte) || (intrinsic == NI_Vector64_AsDouble) || + (intrinsic == NI_Vector64_AsInt16) || (intrinsic == NI_Vector64_AsInt32) || + (intrinsic == NI_Vector64_AsInt64) || (intrinsic == NI_Vector64_AsSByte) || + (intrinsic == NI_Vector64_AsSingle) || (intrinsic == NI_Vector64_AsUInt16) || + (intrinsic == NI_Vector64_AsUInt32) || (intrinsic == NI_Vector64_AsUInt64) || + (intrinsic == NI_Vector64_get_AllBitsSet) || (intrinsic == NI_Vector64_get_Count) || + (intrinsic == NI_Vector64_get_Zero) || (intrinsic == NI_Vector64_GetElement) || + (intrinsic == NI_Vector64_ToScalar) || (intrinsic == NI_Vector64_ToVector128) || + (intrinsic == NI_Vector64_ToVector128Unsafe) || (intrinsic == NI_Vector64_WithElement) || + (intrinsic == NI_Vector128_As) || (intrinsic == NI_Vector128_AsByte) || + (intrinsic == NI_Vector128_AsDouble) || (intrinsic == NI_Vector128_AsInt16) || + (intrinsic == NI_Vector128_AsInt32) || (intrinsic == NI_Vector128_AsInt64) || + (intrinsic == NI_Vector128_AsSByte) || (intrinsic == NI_Vector128_AsSingle) || + (intrinsic == NI_Vector128_AsUInt16) || (intrinsic == NI_Vector128_AsUInt32) || + (intrinsic == NI_Vector128_AsUInt64) || (intrinsic == NI_Vector128_get_AllBitsSet) || + (intrinsic == NI_Vector128_get_Count) || (intrinsic == NI_Vector128_get_Zero) || + (intrinsic == NI_Vector128_GetElement) || (intrinsic == NI_Vector128_GetLower) || + (intrinsic == NI_Vector128_GetUpper) || (intrinsic == NI_Vector128_ToScalar) || + (intrinsic == NI_Vector128_WithElement)); #endif // TARGET_ARM64 -#endif // DEBUG return false; } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 3c01e665ddc32..316ea1670e4ed 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -862,10 +862,26 @@ void Compiler::impPopCallArgs(CORINFO_SIG_INFO* sig, GenTreeCall* call) // Morph trees that aren't already OBJs or MKREFANY to be OBJs assert(ti.IsType(TI_STRUCT)); + bool forceNormalization = false; + if (varTypeIsSIMD(argNode)) + { + // We need to ensure that fgMorphArgs will use the correct struct handle to ensure proper + // ABI handling of this argument. + // Note that this can happen, for example, if we have a SIMD intrinsic that returns a SIMD type + // with a different baseType than we've seen. + // We also need to ensure an OBJ node if we have a FIELD node that might be transformed to LCL_FLD + // or a plain GT_IND. + // TODO-Cleanup: Consider whether we can eliminate all of these cases. + if ((gtGetStructHandleIfPresent(argNode) != classHnd) || argNode->OperIs(GT_FIELD)) + { + forceNormalization = true; + } + } + JITDUMP("Calling impNormStructVal on:\n"); DISPTREE(argNode); - argNode = impNormStructVal(argNode, classHnd, spillCheckLevel); + argNode = impNormStructVal(argNode, classHnd, spillCheckLevel, forceNormalization); // For SIMD types the normalization can normalize TYP_STRUCT to // e.g. TYP_SIMD16 which we keep (along with the class handle) in // the CallArgs. @@ -1388,7 +1404,10 @@ GenTree* Compiler::impAssignStructPtr(GenTree* destAddr, else if (src->OperIsBlk()) { asgType = impNormStructType(structHnd); - assert(ClassLayout::AreCompatible(src->AsBlk()->GetLayout(), typGetObjLayout(structHnd))); + if (src->gtOper == GT_OBJ) + { + assert(src->AsObj()->GetLayout()->GetClassHandle() == structHnd); + } } else if (src->gtOper == GT_MKREFANY) { @@ -1631,7 +1650,7 @@ GenTree* Compiler::impGetStructAddr(GenTree* structVal, // be modified to one that is handled specially by the JIT, possibly being a candidate // for full enregistration, e.g. TYP_SIMD16. If the size of the struct is already known // call structSizeMightRepresentSIMDType to determine if this api needs to be called. -// + var_types Compiler::impNormStructType(CORINFO_CLASS_HANDLE structHnd, CorInfoType* pSimdBaseJitType) { assert(structHnd != NO_CLASS_HANDLE); @@ -1675,6 +1694,7 @@ var_types Compiler::impNormStructType(CORINFO_CLASS_HANDLE structHnd, CorInfoTyp // structVal - the node we are going to normalize // structHnd - the class handle for the node // curLevel - the current stack level +// forceNormalization - Force the creation of an OBJ node (default is false). // // Notes: // Given struct value 'structVal', make sure it is 'canonical', that is @@ -1684,9 +1704,12 @@ var_types Compiler::impNormStructType(CORINFO_CLASS_HANDLE structHnd, CorInfoTyp // - a node (e.g. GT_FIELD) that will be morphed. // If the node is a CALL or RET_EXPR, a copy will be made to a new temp. // -GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE structHnd, unsigned curLevel) +GenTree* Compiler::impNormStructVal(GenTree* structVal, + CORINFO_CLASS_HANDLE structHnd, + unsigned curLevel, + bool forceNormalization /*=false*/) { - assert(varTypeIsStruct(structVal)); + assert(forceNormalization || varTypeIsStruct(structVal)); assert(structHnd != NO_CLASS_HANDLE); var_types structType = structVal->TypeGet(); bool makeTemp = false; @@ -1700,20 +1723,27 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str genTreeOps oper = structVal->OperGet(); switch (oper) { - // GT_MKREFANY is supported directly by args morphing. + // GT_RETURN and GT_MKREFANY don't capture the handle. + case GT_RETURN: + break; case GT_MKREFANY: alreadyNormalized = true; break; case GT_CALL: + structVal->AsCall()->gtRetClsHnd = structHnd; + makeTemp = true; + break; + case GT_RET_EXPR: - makeTemp = true; + structVal->AsRetExpr()->gtRetClsHnd = structHnd; + makeTemp = true; break; case GT_FIELD: // Wrap it in a GT_OBJ, if needed. structVal->gtType = structType; - if (structType == TYP_STRUCT) + if ((structType == TYP_STRUCT) || forceNormalization) { structVal = gtNewObjNode(structHnd, gtNewOperNode(GT_ADDR, TYP_BYREF, structVal)); } @@ -1728,6 +1758,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str case GT_OBJ: case GT_BLK: + case GT_ASG: // These should already have the appropriate type. assert(structVal->gtType == structType); alreadyNormalized = true; @@ -1740,8 +1771,10 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str break; case GT_CNS_VEC: + { assert(varTypeIsSIMD(structVal) && (structVal->gtType == structType)); break; + } #ifdef FEATURE_SIMD case GT_SIMD: @@ -1784,7 +1817,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str #ifdef FEATURE_SIMD if (blockNode->OperIsSimdOrHWintrinsic() || blockNode->IsCnsVec()) { - parent->AsOp()->gtOp2 = impNormStructVal(blockNode, structHnd, curLevel); + parent->AsOp()->gtOp2 = impNormStructVal(blockNode, structHnd, curLevel, forceNormalization); alreadyNormalized = true; } else @@ -1819,7 +1852,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str } structVal->gtType = structType; - if (!alreadyNormalized) + if (!alreadyNormalized || forceNormalization) { if (makeTemp) { @@ -1832,7 +1865,7 @@ GenTree* Compiler::impNormStructVal(GenTree* structVal, CORINFO_CLASS_HANDLE str structLcl = gtNewLclvNode(tmpNum, structType)->AsLclVarCommon(); structVal = structLcl; } - if ((structType == TYP_STRUCT) && !structVal->OperIsBlk()) + if ((forceNormalization || (structType == TYP_STRUCT)) && !structVal->OperIsBlk()) { // Wrap it in a GT_OBJ structVal = gtNewObjNode(structHnd, gtNewOperNode(GT_ADDR, TYP_BYREF, structVal)); @@ -1905,8 +1938,8 @@ GenTree* Compiler::impTokenToHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken, } // Generate the full lookup tree. May be null if we're abandoning an inline attempt. - GenTreeFlags handleType = importParent ? GTF_ICON_CLASS_HDL : gtTokenToIconFlags(pResolvedToken->token); - GenTree* result = impLookupToTree(pResolvedToken, &embedInfo.lookup, handleType, embedInfo.compileTimeHandle); + GenTree* result = impLookupToTree(pResolvedToken, &embedInfo.lookup, gtTokenToIconFlags(pResolvedToken->token), + embedInfo.compileTimeHandle); // If we have a result and it requires runtime lookup, wrap it in a runtime lookup node. if ((result != nullptr) && embedInfo.lookup.lookupKind.needsRuntimeLookup) @@ -8820,7 +8853,9 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT // Create the address node. GenTreeFlags handleKind = isBoxedStatic ? GTF_ICON_STATIC_BOX_PTR : GTF_ICON_STATIC_HDL; op1 = gtNewIconHandleNode((size_t)fldAddr, handleKind, innerFldSeq); - INDEBUG(op1->AsIntCon()->gtTargetHandle = reinterpret_cast(pResolvedToken->hField)); +#ifdef DEBUG + op1->AsIntCon()->gtTargetHandle = op1->AsIntCon()->gtIconVal; +#endif if (pFieldInfo->fieldFlags & CORINFO_FLG_FIELD_INITCLASS) { @@ -10047,23 +10082,11 @@ var_types Compiler::impImportCall(OPCODE opcode, call->gtFlags |= obj->gtFlags & GTF_GLOB_EFFECT; call->AsCall()->gtArgs.PushFront(this, NewCallArg::Primitive(obj).WellKnown(WellKnownArg::ThisPointer)); - if (impIsThis(obj)) - { - call->AsCall()->gtCallMoreFlags |= GTF_CALL_M_NONVIRT_SAME_THIS; - } - } - - bool probing; - probing = impConsiderCallProbe(call->AsCall(), rawILOffset); - - // See if we can devirt if we aren't probing. - if (!probing && opts.OptimizationEnabled()) - { + // Is this a virtual or interface call? if (call->AsCall()->IsVirtual()) { // only true object pointers can be virtual - assert(call->AsCall()->gtArgs.HasThisPointer() && - call->AsCall()->gtArgs.GetThisArg()->GetNode()->TypeIs(TYP_REF)); + assert(obj->gtType == TYP_REF); // See if we can devirtualize. @@ -10079,10 +10102,10 @@ var_types Compiler::impImportCall(OPCODE opcode, // methHnd = callInfo->hMethod; } - else if (call->AsCall()->IsDelegateInvoke()) + + if (impIsThis(obj)) { - considerGuardedDevirtualization(call->AsCall(), rawILOffset, false, NO_METHOD_HANDLE, NO_CLASS_HANDLE, - nullptr); + call->AsCall()->gtCallMoreFlags |= GTF_CALL_M_NONVIRT_SAME_THIS; } } @@ -10519,7 +10542,7 @@ var_types Compiler::impImportCall(OPCODE opcode, // important devirtualizations, we'll want to allow both a class probe and a captured context. // if (origCall->IsVirtual() && (origCall->gtCallType != CT_INDIRECT) && (exactContextHnd != nullptr) && - (origCall->gtHandleHistogramProfileCandidateInfo == nullptr)) + (origCall->gtClassProfileCandidateInfo == nullptr)) { JITDUMP("\nSaving context %p for call [%06u]\n", exactContextHnd, dspTreeID(origCall)); origCall->gtCallMoreFlags |= GTF_CALL_M_HAS_LATE_DEVIRT_INFO; @@ -12129,31 +12152,38 @@ GenTree* Compiler::impCastClassOrIsInstToTree( // Check if this cast helper have some profile data if (impIsCastHelperMayHaveProfileData(helper)) { - const int maxLikelyClasses = 32; - LikelyClassMethodRecord likelyClasses[maxLikelyClasses]; - unsigned likelyClassCount = - getLikelyClasses(likelyClasses, maxLikelyClasses, fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset); + bool doRandomDevirt = false; + const int maxLikelyClasses = 32; + int likelyClassCount = 0; + LikelyClassRecord likelyClasses[maxLikelyClasses]; +#ifdef DEBUG + // Optional stress mode to pick a random known class, rather than + // the most likely known class. + doRandomDevirt = JitConfig.JitRandomGuardedDevirtualization() != 0; - if (likelyClassCount > 0) + if (doRandomDevirt) { -#ifdef DEBUG - // Optional stress mode to pick a random known class, rather than - // the most likely known class. - if (JitConfig.JitRandomGuardedDevirtualization() != 0) + // Reuse the random inliner's random state. + CLRRandom* const random = + impInlineRoot()->m_inlineStrategy->GetRandom(JitConfig.JitRandomGuardedDevirtualization()); + likelyClasses[0].clsHandle = getRandomClass(fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset, random); + likelyClasses[0].likelihood = 100; + if (likelyClasses[0].clsHandle != NO_CLASS_HANDLE) { - // Reuse the random inliner's random state. - CLRRandom* const random = - impInlineRoot()->m_inlineStrategy->GetRandom(JitConfig.JitRandomGuardedDevirtualization()); - - unsigned index = static_cast(random->Next(static_cast(likelyClassCount))); - likelyClasses[0].handle = likelyClasses[index].handle; - likelyClasses[0].likelihood = 100; - likelyClassCount = 1; + likelyClassCount = 1; } + } + else #endif + { + likelyClassCount = getLikelyClasses(likelyClasses, maxLikelyClasses, fgPgoSchema, fgPgoSchemaCount, + fgPgoData, ilOffset); + } - LikelyClassMethodRecord likelyClass = likelyClasses[0]; - CORINFO_CLASS_HANDLE likelyCls = (CORINFO_CLASS_HANDLE)likelyClass.handle; + if (likelyClassCount > 0) + { + LikelyClassRecord likelyClass = likelyClasses[0]; + CORINFO_CLASS_HANDLE likelyCls = likelyClass.clsHandle; if ((likelyCls != NO_CLASS_HANDLE) && (likelyClass.likelihood > (UINT32)JitConfig.JitGuardedDevirtualizationChainLikelihood())) @@ -12188,14 +12218,13 @@ GenTree* Compiler::impCastClassOrIsInstToTree( op2->gtFlags |= GTF_DONT_CSE; GenTreeCall* call = gtNewHelperCallNode(helper, TYP_REF, op2, op1); - if ((JitConfig.JitClassProfiling() > 0) && impIsCastHelperEligibleForClassProbe(call) && - !impIsClassExact(pResolvedToken->hClass)) + if (impIsCastHelperEligibleForClassProbe(call) && !impIsClassExact(pResolvedToken->hClass)) { - HandleHistogramProfileCandidateInfo* pInfo = new (this, CMK_Inlining) HandleHistogramProfileCandidateInfo; - pInfo->ilOffset = ilOffset; - pInfo->probeIndex = info.compHandleHistogramProbeCount++; - call->gtHandleHistogramProfileCandidateInfo = pInfo; - compCurBB->bbFlags |= BBF_HAS_HISTOGRAM_PROFILE; + ClassProfileCandidateInfo* pInfo = new (this, CMK_Inlining) ClassProfileCandidateInfo; + pInfo->ilOffset = ilOffset; + pInfo->probeIndex = info.compClassProbeCount++; + call->gtClassProfileCandidateInfo = pInfo; + compCurBB->bbFlags |= BBF_HAS_CLASS_PROFILE; } return call; } @@ -19878,8 +19907,8 @@ void Compiler::impCheckCanInline(GenTreeCall* call, if (pParam->result->IsFailure()) { - // Do not report this as a failure. Instead report as a "VM failure" - pParam->result->SetVMFailure(); + // Make sure not to report this one. It was already reported by the VM. + pParam->result->SetReported(); goto _exit; } @@ -20987,7 +21016,7 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call, // Delegate Invoke method doesn't have a body and gets special cased instead. // Don't even bother trying to inline it. - if (call->IsDelegateInvoke() && !call->IsGuardedDevirtualizationCandidate()) + if (call->IsDelegateInvoke()) { inlineResult.NoteFatal(InlineObservation::CALLEE_HAS_NO_BODY); return; @@ -21172,7 +21201,7 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call, // Since we're not actually inlining yet, and this call site is // still just an inline candidate, there's nothing to report. - inlineResult.SetSuccessResult(INLINE_CHECK_CAN_INLINE_SUCCESS); + inlineResult.SetReported(); } /******************************************************************************/ @@ -21372,7 +21401,51 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, // This should be a virtual vtable or virtual stub call. // assert(call->IsVirtual()); - assert(opts.OptimizationEnabled()); + + // Possibly instrument. Note for OSR+PGO we will instrument when + // optimizing and (currently) won't devirtualize. We may want + // to revisit -- if we can devirtualize we should be able to + // suppress the probe. + // + // We strip BBINSTR from inlinees currently, so we'll only + // do this for the root method calls. + // + if (opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR)) + { + assert(opts.OptimizationDisabled() || opts.IsOSR()); + assert(!compIsForInlining()); + + // During importation, optionally flag this block as one that + // contains calls requiring class profiling. Ideally perhaps + // we'd just keep track of the calls themselves, so we don't + // have to search for them later. + // + if ((call->gtCallType != CT_INDIRECT) && opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR) && + !opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT) && (JitConfig.JitClassProfiling() > 0) && + !isLateDevirtualization) + { + JITDUMP("\n ... marking [%06u] in " FMT_BB " for class profile instrumentation\n", dspTreeID(call), + compCurBB->bbNum); + ClassProfileCandidateInfo* pInfo = new (this, CMK_Inlining) ClassProfileCandidateInfo; + + // Record some info needed for the class profiling probe. + // + pInfo->ilOffset = ilOffset; + pInfo->probeIndex = info.compClassProbeCount++; + call->gtClassProfileCandidateInfo = pInfo; + + // Flag block as needing scrutiny + // + compCurBB->bbFlags |= BBF_HAS_CLASS_PROFILE; + } + return; + } + + // Bail if optimizations are disabled. + if (opts.OptimizationDisabled()) + { + return; + } #if defined(DEBUG) // Bail if devirt is disabled. @@ -21464,7 +21537,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, return; } - considerGuardedDevirtualization(call, ilOffset, isInterface, baseMethod, baseClass, pContextHandle); + considerGuardedDevirtualization(call, ilOffset, isInterface, baseMethod, baseClass, + pContextHandle DEBUGARG(objClass) DEBUGARG("unknown")); return; } @@ -21514,7 +21588,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, return; } - considerGuardedDevirtualization(call, ilOffset, isInterface, baseMethod, baseClass, pContextHandle); + considerGuardedDevirtualization(call, ilOffset, isInterface, baseMethod, baseClass, + pContextHandle DEBUGARG(objClass) DEBUGARG(objClassName)); return; } @@ -21630,7 +21705,8 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, return; } - considerGuardedDevirtualization(call, ilOffset, isInterface, baseMethod, baseClass, pContextHandle); + considerGuardedDevirtualization(call, ilOffset, isInterface, baseMethod, baseClass, + pContextHandle DEBUGARG(objClass) DEBUGARG(objClassName)); return; } @@ -21650,7 +21726,6 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, call->gtFlags &= ~GTF_CALL_VIRT_STUB; call->gtCallMethHnd = derivedMethod; call->gtCallType = CT_USER_FUNC; - call->gtControlExpr = nullptr; call->gtCallMoreFlags |= GTF_CALL_M_DEVIRTUALIZED; // Virtual calls include an implicit null check, which we may @@ -21692,14 +21767,14 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, if (JitConfig.JitCrossCheckDevirtualizationAndPGO() && canSensiblyCheck) { // We only can handle a single likely class for now - const int maxLikelyClasses = 1; - LikelyClassMethodRecord likelyClasses[maxLikelyClasses]; + const int maxLikelyClasses = 1; + LikelyClassRecord likelyClasses[maxLikelyClasses]; UINT32 numberOfClasses = getLikelyClasses(likelyClasses, maxLikelyClasses, fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset); UINT32 likelihood = likelyClasses[0].likelihood; - CORINFO_CLASS_HANDLE likelyClass = (CORINFO_CLASS_HANDLE)likelyClasses[0].handle; + CORINFO_CLASS_HANDLE likelyClass = likelyClasses[0].clsHandle; if (numberOfClasses > 0) { @@ -21990,117 +22065,6 @@ void Compiler::impDevirtualizeCall(GenTreeCall* call, #endif // FEATURE_READYTORUN } -//------------------------------------------------------------------------ -// impConsiderCallProbe: Consider whether a call should get a histogram probe -// and mark it if so. -// -// Arguments: -// call - The call -// ilOffset - The precise IL offset of the call -// -// Returns: -// True if the call was marked such that we will add a class or method probe for it. -// -bool Compiler::impConsiderCallProbe(GenTreeCall* call, IL_OFFSET ilOffset) -{ - // Possibly instrument. Note for OSR+PGO we will instrument when - // optimizing and (currently) won't devirtualize. We may want - // to revisit -- if we can devirtualize we should be able to - // suppress the probe. - // - // We strip BBINSTR from inlinees currently, so we'll only - // do this for the root method calls. - // - if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR)) - { - return false; - } - - assert(opts.OptimizationDisabled() || opts.IsOSR()); - assert(!compIsForInlining()); - - // During importation, optionally flag this block as one that - // contains calls requiring class profiling. Ideally perhaps - // we'd just keep track of the calls themselves, so we don't - // have to search for them later. - // - if (compClassifyGDVProbeType(call) == GDVProbeType::None) - { - return false; - } - - JITDUMP("\n ... marking [%06u] in " FMT_BB " for method/class profile instrumentation\n", dspTreeID(call), - compCurBB->bbNum); - HandleHistogramProfileCandidateInfo* pInfo = new (this, CMK_Inlining) HandleHistogramProfileCandidateInfo; - - // Record some info needed for the class profiling probe. - // - pInfo->ilOffset = ilOffset; - pInfo->probeIndex = info.compHandleHistogramProbeCount++; - call->gtHandleHistogramProfileCandidateInfo = pInfo; - - // Flag block as needing scrutiny - // - compCurBB->bbFlags |= BBF_HAS_HISTOGRAM_PROFILE; - return true; -} - -//------------------------------------------------------------------------ -// compClassifyGDVProbeType: -// Classify the type of GDV probe to use for a call site. -// -// Arguments: -// call - The call -// -// Returns: -// The type of probe to use. -// -Compiler::GDVProbeType Compiler::compClassifyGDVProbeType(GenTreeCall* call) -{ - if (call->gtCallType == CT_INDIRECT) - { - return GDVProbeType::None; - } - - if (!opts.jitFlags->IsSet(JitFlags::JIT_FLAG_BBINSTR) || opts.jitFlags->IsSet(JitFlags::JIT_FLAG_PREJIT)) - { - return GDVProbeType::None; - } - - bool createTypeHistogram = false; - if (JitConfig.JitClassProfiling() > 0) - { - createTypeHistogram = call->IsVirtualStub() || call->IsVirtualVtable(); - - // Cast helpers may conditionally (depending on whether the class is - // exact or not) have probes. For those helpers we do not use this - // function to classify the probe type until after we have decided on - // whether we probe them or not. - createTypeHistogram = createTypeHistogram || (impIsCastHelperEligibleForClassProbe(call) && - (call->gtHandleHistogramProfileCandidateInfo != nullptr)); - } - - bool createMethodHistogram = ((JitConfig.JitDelegateProfiling() > 0) && call->IsDelegateInvoke()) || - ((JitConfig.JitVTableProfiling() > 0) && call->IsVirtualVtable()); - - if (createTypeHistogram && createMethodHistogram) - { - return GDVProbeType::MethodAndClassProfile; - } - - if (createTypeHistogram) - { - return GDVProbeType::ClassProfile; - } - - if (createMethodHistogram) - { - return GDVProbeType::MethodProfile; - } - - return GDVProbeType::None; -} - //------------------------------------------------------------------------ // impGetSpecialIntrinsicExactReturnType: Look for special cases where a call // to an intrinsic returns an exact type @@ -22111,6 +22075,7 @@ Compiler::GDVProbeType Compiler::compClassifyGDVProbeType(GenTreeCall* call) // Returns: // Exact class handle returned by the intrinsic call, if known. // Nullptr if not known, or not likely to lead to beneficial optimization. + CORINFO_CLASS_HANDLE Compiler::impGetSpecialIntrinsicExactReturnType(CORINFO_METHOD_HANDLE methodHnd) { JITDUMP("Special intrinsic: looking for exact type returned by %s\n", eeGetMethodFullName(methodHnd)); @@ -22272,380 +22237,153 @@ void Compiler::addFatPointerCandidate(GenTreeCall* call) } //------------------------------------------------------------------------ -// pickGDV: Use profile information to pick a GDV candidate for a call site. +// considerGuardedDevirtualization: see if we can profitably guess at the +// class involved in an interface or virtual call. // // Arguments: -// call - the call -// ilOffset - exact IL offset of the call -// isInterface - whether or not the call target is defined on an interface -// classGuess - [out] the class to guess for (mutually exclusive with methodGuess) -// methodGuess - [out] the method to guess for (mutually exclusive with classGuess) -// likelihood - [out] an estimate of the likelihood that the guess will succeed // -void Compiler::pickGDV(GenTreeCall* call, - IL_OFFSET ilOffset, - bool isInterface, - CORINFO_CLASS_HANDLE* classGuess, - CORINFO_METHOD_HANDLE* methodGuess, - unsigned* likelihood) +// call - potential guarded devirtualization candidate +// ilOffset - IL ofset of the call instruction +// isInterface - true if this is an interface call +// baseMethod - target method of the call +// baseClass - class that introduced the target method +// pContextHandle - context handle for the call +// objClass - class of 'this' in the call +// objClassName - name of the obj Class +// +// Notes: +// Consults with VM to see if there's a likely class at runtime, +// if so, adds a candidate for guarded devirtualization. +// +void Compiler::considerGuardedDevirtualization( + GenTreeCall* call, + IL_OFFSET ilOffset, + bool isInterface, + CORINFO_METHOD_HANDLE baseMethod, + CORINFO_CLASS_HANDLE baseClass, + CORINFO_CONTEXT_HANDLE* pContextHandle DEBUGARG(CORINFO_CLASS_HANDLE objClass) DEBUGARG(const char* objClassName)) { - *classGuess = NO_CLASS_HANDLE; - *methodGuess = NO_METHOD_HANDLE; - *likelihood = 0; - - const int maxLikelyClasses = 32; - LikelyClassMethodRecord likelyClasses[maxLikelyClasses]; - unsigned numberOfClasses = 0; - if (call->IsVirtualStub() || call->IsVirtualVtable()) - { - numberOfClasses = - getLikelyClasses(likelyClasses, maxLikelyClasses, fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset); - } +#if defined(DEBUG) + const char* callKind = isInterface ? "interface" : "virtual"; +#endif - const int maxLikelyMethods = 32; - LikelyClassMethodRecord likelyMethods[maxLikelyMethods]; - unsigned numberOfMethods = 0; + JITDUMP("Considering guarded devirtualization at IL offset %u (0x%x)\n", ilOffset, ilOffset); - // TODO-GDV: R2R support requires additional work to reacquire the - // entrypoint, similar to what happens at the end of impDevirtualizeCall. - // As part of supporting this we should merge the tail of - // impDevirtualizeCall and what happens in - // GuardedDevirtualizationTransformer::CreateThen for method GDV. + // We currently only get likely class guesses when there is PGO data + // with class profiles. // - if (!opts.IsReadyToRun() && (call->IsVirtualVtable() || call->IsDelegateInvoke())) + if (fgPgoClassProfiles == 0) { - numberOfMethods = - getLikelyMethods(likelyMethods, maxLikelyMethods, fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset); - } - - if ((numberOfClasses < 1) && (numberOfMethods < 1)) - { - JITDUMP("No likely class or method, sorry\n"); + JITDUMP("Not guessing for class: no class profile pgo data, or pgo disabled\n"); return; } -#ifdef DEBUG - if ((verbose || JitConfig.EnableExtraSuperPmiQueries()) && (numberOfClasses > 0)) - { - bool isExact; - bool isNonNull; - CallArg* thisArg = call->gtArgs.GetThisArg(); - CORINFO_CLASS_HANDLE declaredThisClsHnd = gtGetClassHandle(thisArg->GetNode(), &isExact, &isNonNull); - JITDUMP("Likely classes for call [%06u]", dspTreeID(call)); - if (declaredThisClsHnd != NO_CLASS_HANDLE) - { - const char* baseClassName = eeGetClassName(declaredThisClsHnd); - JITDUMP(" on class %p (%s)", declaredThisClsHnd, baseClassName); - } - JITDUMP("\n"); + // See if there's a likely guess for the class. + // + const unsigned likelihoodThreshold = isInterface ? 25 : 30; + unsigned likelihood = 0; + unsigned numberOfClasses = 0; - for (UINT32 i = 0; i < numberOfClasses; i++) - { - const char* className = eeGetClassName((CORINFO_CLASS_HANDLE)likelyClasses[i].handle); - JITDUMP(" %u) %p (%s) [likelihood:%u%%]\n", i + 1, likelyClasses[i].handle, className, - likelyClasses[i].likelihood); - } - } + CORINFO_CLASS_HANDLE likelyClass = NO_CLASS_HANDLE; - if ((verbose || JitConfig.EnableExtraSuperPmiQueries()) && (numberOfMethods > 0)) - { - assert(call->gtCallType == CT_USER_FUNC); - const char* baseMethName = eeGetMethodFullName(call->gtCallMethHnd); - JITDUMP("Likely methods for call [%06u] to method %s\n", dspTreeID(call), baseMethName); + bool doRandomDevirt = false; - for (UINT32 i = 0; i < numberOfMethods; i++) - { - CORINFO_CONST_LOOKUP lookup = {}; - info.compCompHnd->getFunctionFixedEntryPoint((CORINFO_METHOD_HANDLE)likelyMethods[i].handle, false, - &lookup); - - const char* methName = eeGetMethodFullName((CORINFO_METHOD_HANDLE)likelyMethods[i].handle); - switch (lookup.accessType) - { - case IAT_VALUE: - JITDUMP(" %u) %p (%s) [likelihood:%u%%]\n", i + 1, lookup.addr, methName, - likelyMethods[i].likelihood); - break; - case IAT_PVALUE: - JITDUMP(" %u) [%p] (%s) [likelihood:%u%%]\n", i + 1, lookup.addr, methName, - likelyMethods[i].likelihood); - break; - case IAT_PPVALUE: - JITDUMP(" %u) [[%p]] (%s) [likelihood:%u%%]\n", i + 1, lookup.addr, methName, - likelyMethods[i].likelihood); - break; - default: - JITDUMP(" %u) %s [likelihood:%u%%]\n", i + 1, methName, likelyMethods[i].likelihood); - break; - } - } - } + const int maxLikelyClasses = 32; + LikelyClassRecord likelyClasses[maxLikelyClasses]; +#ifdef DEBUG // Optional stress mode to pick a random known class, rather than // the most likely known class. // - if (JitConfig.JitRandomGuardedDevirtualization() != 0) + doRandomDevirt = JitConfig.JitRandomGuardedDevirtualization() != 0; + + if (doRandomDevirt) { // Reuse the random inliner's random state. // CLRRandom* const random = impInlineRoot()->m_inlineStrategy->GetRandom(JitConfig.JitRandomGuardedDevirtualization()); - unsigned index = static_cast(random->Next(static_cast(numberOfClasses + numberOfMethods))); - if (index < numberOfClasses) + likelyClasses[0].clsHandle = getRandomClass(fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset, random); + likelyClasses[0].likelihood = 100; + if (likelyClasses[0].clsHandle != NO_CLASS_HANDLE) { - *classGuess = (CORINFO_CLASS_HANDLE)likelyClasses[index].handle; - *likelihood = 100; - JITDUMP("Picked random class for GDV: %p (%s)\n", *classGuess, eeGetClassName(*classGuess)); - return; - } - else - { - *methodGuess = (CORINFO_METHOD_HANDLE)likelyMethods[index - numberOfClasses].handle; - *likelihood = 100; - JITDUMP("Picked random method for GDV: %p (%s)\n", *methodGuess, eeGetMethodFullName(*methodGuess)); - return; + numberOfClasses = 1; } } + else #endif - - // Prefer class guess as it is cheaper - if (numberOfClasses > 0) { - unsigned likelihoodThreshold = isInterface ? 25 : 30; - if (likelyClasses[0].likelihood >= likelihoodThreshold) - { - *classGuess = (CORINFO_CLASS_HANDLE)likelyClasses[0].handle; - *likelihood = likelyClasses[0].likelihood; - return; - } - - JITDUMP("Not guessing for class; likelihood is below %s call threshold %u\n", - isInterface ? "interface" : "virtual", likelihoodThreshold); + numberOfClasses = + getLikelyClasses(likelyClasses, maxLikelyClasses, fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset); } - if (numberOfMethods > 0) - { - unsigned likelihoodThreshold = 30; - if (likelyMethods[0].likelihood >= likelihoodThreshold) - { - *methodGuess = (CORINFO_METHOD_HANDLE)likelyMethods[0].handle; - *likelihood = likelyMethods[0].likelihood; - return; - } + // For now we only use the most popular type - JITDUMP("Not guessing for method; likelihood is below %s call threshold %u\n", - call->IsDelegateInvoke() ? "delegate" : "virtual", likelihoodThreshold); - } -} + likelihood = likelyClasses[0].likelihood; + likelyClass = likelyClasses[0].clsHandle; -//------------------------------------------------------------------------ -// isCompatibleMethodGDV: -// Check if devirtualizing a call node as a specified target method call is -// reasonable. -// -// Arguments: -// call - the call -// gdvTarget - the target method that we want to guess for and devirtualize to -// -// Returns: -// true if we can proceed with GDV. -// -// Notes: -// This implements a small simplified signature-compatibility check to -// verify that a guess is reasonable. The main goal here is to avoid blowing -// up the JIT on PGO data with stale GDV candidates; if they are not -// compatible in the ECMA sense then we do not expect the guard to ever pass -// at runtime, so we can get by with simplified rules here. -// -bool Compiler::isCompatibleMethodGDV(GenTreeCall* call, CORINFO_METHOD_HANDLE gdvTarget) -{ - CORINFO_SIG_INFO sig; - info.compCompHnd->getMethodSig(gdvTarget, &sig); - - CORINFO_ARG_LIST_HANDLE sigParam = sig.args; - unsigned numParams = sig.numArgs; - unsigned numArgs = 0; - for (CallArg& arg : call->gtArgs.Args()) + if (numberOfClasses < 1) { - switch (arg.GetWellKnownArg()) - { - case WellKnownArg::RetBuffer: - case WellKnownArg::ThisPointer: - // Not part of signature but we still expect to see it here - continue; - case WellKnownArg::None: - break; - default: - assert(!"Unexpected well known arg to method GDV candidate"); - continue; - } - - numArgs++; - if (numArgs > numParams) - { - JITDUMP("Incompatible method GDV: call [%06u] has more arguments than signature (sig has %d parameters)\n", - dspTreeID(call), numParams); - return false; - } - - CORINFO_CLASS_HANDLE classHnd = NO_CLASS_HANDLE; - CorInfoType corType = strip(info.compCompHnd->getArgType(&sig, sigParam, &classHnd)); - var_types sigType = JITtype2varType(corType); - - if (!impCheckImplicitArgumentCoercion(sigType, arg.GetNode()->TypeGet())) - { - JITDUMP("Incompatible method GDV: arg [%06u] is type-incompatible with signature of target\n", - dspTreeID(arg.GetNode())); - return false; - } - - // Best-effort check for struct compatibility here. - if (varTypeIsStruct(sigType) && (arg.GetSignatureClassHandle() != classHnd)) - { - ClassLayout* callLayout = typGetObjLayout(arg.GetSignatureClassHandle()); - ClassLayout* tarLayout = typGetObjLayout(classHnd); - - if (!ClassLayout::AreCompatible(callLayout, tarLayout)) - { - JITDUMP("Incompatible method GDV: struct arg [%06u] is layout-incompatible with signature of target\n", - dspTreeID(arg.GetNode())); - return false; - } - } - - sigParam = info.compCompHnd->getArgNext(sigParam); + JITDUMP("No likely class, sorry\n"); + return; } - if (numArgs < numParams) + assert(likelyClass != NO_CLASS_HANDLE); + + // Print all likely classes + JITDUMP("%s classes for %p (%s):\n", doRandomDevirt ? "Random" : "Likely", dspPtr(objClass), objClassName) + for (UINT32 i = 0; i < numberOfClasses; i++) { - JITDUMP("Incompatible method GDV: call [%06u] has fewer arguments (%d) than signature (%d)\n", dspTreeID(call), - numArgs, numParams); - return false; + JITDUMP(" %u) %p (%s) [likelihood:%u%%]\n", i + 1, likelyClasses[i].clsHandle, + eeGetClassName(likelyClasses[i].clsHandle), likelyClasses[i].likelihood); } - return true; -} - -//------------------------------------------------------------------------ -// considerGuardedDevirtualization: see if we can profitably guess at the -// class involved in an interface or virtual call. -// -// Arguments: -// -// call - potential guarded devirtualization candidate -// ilOffset - IL ofset of the call instruction -// baseMethod - target method of the call -// baseClass - class that introduced the target method -// pContextHandle - context handle for the call -// -// Notes: -// Consults with VM to see if there's a likely class at runtime, -// if so, adds a candidate for guarded devirtualization. -// -void Compiler::considerGuardedDevirtualization(GenTreeCall* call, - IL_OFFSET ilOffset, - bool isInterface, - CORINFO_METHOD_HANDLE baseMethod, - CORINFO_CLASS_HANDLE baseClass, - CORINFO_CONTEXT_HANDLE* pContextHandle) -{ - JITDUMP("Considering guarded devirtualization at IL offset %u (0x%x)\n", ilOffset, ilOffset); - - // We currently only get likely class guesses when there is PGO data - // with class profiles. + // Todo: a more advanced heuristic using likelihood, number of + // classes, and the profile count for this block. // - if ((fgPgoClassProfiles == 0) && (fgPgoMethodProfiles == 0)) + // For now we will guess if the likelihood is at least 25%/30% (intfc/virt), as studies + // have shown this transformation should pay off even if we guess wrong sometimes. + // + if (likelihood < likelihoodThreshold) { - JITDUMP("Not guessing for class or method: no GDV profile pgo data, or pgo disabled\n"); + JITDUMP("Not guessing for class; likelihood is below %s call threshold %u\n", callKind, likelihoodThreshold); return; } - CORINFO_CLASS_HANDLE likelyClass; - CORINFO_METHOD_HANDLE likelyMethod; - unsigned likelihood; - pickGDV(call, ilOffset, isInterface, &likelyClass, &likelyMethod, &likelihood); + uint32_t const likelyClassAttribs = info.compCompHnd->getClassAttribs(likelyClass); - if ((likelyClass == NO_CLASS_HANDLE) && (likelyMethod == NO_METHOD_HANDLE)) + if ((likelyClassAttribs & CORINFO_FLG_ABSTRACT) != 0) { + // We may see an abstract likely class, if we have a stale profile. + // No point guessing for this. + // + JITDUMP("Not guessing for class; abstract (stale profile)\n"); return; } - uint32_t likelyClassAttribs = 0; - if (likelyClass != NO_CLASS_HANDLE) - { - likelyClassAttribs = info.compCompHnd->getClassAttribs(likelyClass); - - if ((likelyClassAttribs & CORINFO_FLG_ABSTRACT) != 0) - { - // We may see an abstract likely class, if we have a stale profile. - // No point guessing for this. - // - JITDUMP("Not guessing for class; abstract (stale profile)\n"); - return; - } - - // Figure out which method will be called. - // - CORINFO_DEVIRTUALIZATION_INFO dvInfo; - dvInfo.virtualMethod = baseMethod; - dvInfo.objClass = likelyClass; - dvInfo.context = *pContextHandle; - dvInfo.exactContext = *pContextHandle; - dvInfo.pResolvedTokenVirtualMethod = nullptr; - - const bool canResolve = info.compCompHnd->resolveVirtualMethod(&dvInfo); - - if (!canResolve) - { - JITDUMP("Can't figure out which method would be invoked, sorry\n"); - return; - } - - likelyMethod = dvInfo.devirtualizedMethod; - } + // Figure out which method will be called. + // + CORINFO_DEVIRTUALIZATION_INFO dvInfo; + dvInfo.virtualMethod = baseMethod; + dvInfo.objClass = likelyClass; + dvInfo.context = *pContextHandle; + dvInfo.exactContext = *pContextHandle; + dvInfo.pResolvedTokenVirtualMethod = nullptr; - uint32_t likelyMethodAttribs = info.compCompHnd->getMethodAttribs(likelyMethod); + const bool canResolve = info.compCompHnd->resolveVirtualMethod(&dvInfo); - if (likelyClass == NO_CLASS_HANDLE) + if (!canResolve) { - // For method GDV do a few more checks that we get for free in the - // resolve call above for class-based GDV. - if ((likelyMethodAttribs & CORINFO_FLG_STATIC) != 0) - { - assert(call->IsDelegateInvoke()); - JITDUMP("Cannot currently handle devirtualizing static delegate calls, sorry\n"); - return; - } - - // Verify that the call target and args look reasonable so that the JIT - // does not blow up during inlining/call morphing. - // - // NOTE: Once we want to support devirtualization of delegate calls to - // static methods and remove the check above we will start failing here - // for delegates pointing to static methods that have the first arg - // bound. For example: - // - // public static void E(this C c) ... - // Action a = new C().E; - // - // The delegate instance looks exactly like one pointing to an instance - // method in this case and the call will have zero args while the - // signature has 1 arg. - // - if (!isCompatibleMethodGDV(call, likelyMethod)) - { - JITDUMP("Target for method-based GDV is incompatible (stale profile?)\n"); - assert((fgPgoSource != ICorJitInfo::PgoSource::Dynamic) && "Unexpected stale profile in dynamic PGO data"); - return; - } + JITDUMP("Can't figure out which method would be invoked, sorry\n"); + return; } - JITDUMP("%s call would invoke method %s\n", - isInterface ? "interface" : call->IsDelegateInvoke() ? "delegate" : "virtual", - eeGetMethodName(likelyMethod, nullptr)); + CORINFO_METHOD_HANDLE likelyMethod = dvInfo.devirtualizedMethod; + JITDUMP("%s call would invoke method %s\n", callKind, eeGetMethodName(likelyMethod, nullptr)); // Add this as a potential candidate. // + uint32_t const likelyMethodAttribs = info.compCompHnd->getMethodAttribs(likelyMethod); addGuardedDevirtualizationCandidate(call, likelyMethod, likelyClass, likelyMethodAttribs, likelyClassAttribs, likelihood); } @@ -22678,8 +22416,8 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call, unsigned classAttr, unsigned likelihood) { - // This transformation only makes sense for delegate and virtual calls - assert(call->IsDelegateInvoke() || call->IsVirtual()); + // This transformation only makes sense for virtual calls + assert(call->IsVirtual()); // Only mark calls if the feature is enabled. const bool isEnabled = JitConfig.JitEnableGuardedDevirtualization() > 0; @@ -22729,9 +22467,8 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call, // We're all set, proceed with candidate creation. // - JITDUMP("Marking call [%06u] as guarded devirtualization candidate; will guess for %s %s\n", dspTreeID(call), - classHandle != NO_CLASS_HANDLE ? "class" : "method", - classHandle != NO_CLASS_HANDLE ? eeGetClassName(classHandle) : eeGetMethodFullName(methodHandle)); + JITDUMP("Marking call [%06u] as guarded devirtualization candidate; will guess for class %s\n", dspTreeID(call), + eeGetClassName(classHandle)); setMethodHasGuardedDevirtualization(); call->SetGuardedDevirtualizationCandidate(); diff --git a/src/coreclr/jit/indirectcalltransformer.cpp b/src/coreclr/jit/indirectcalltransformer.cpp index e3d799f734b8b..14242b8f718b9 100644 --- a/src/coreclr/jit/indirectcalltransformer.cpp +++ b/src/coreclr/jit/indirectcalltransformer.cpp @@ -450,11 +450,9 @@ class IndirectCallTransformer class GuardedDevirtualizationTransformer final : public Transformer { - unsigned m_targetLclNum; - public: GuardedDevirtualizationTransformer(Compiler* compiler, BasicBlock* block, Statement* stmt) - : Transformer(compiler, block, stmt), m_targetLclNum(BAD_VAR_NUM), returnTemp(BAD_VAR_NUM) + : Transformer(compiler, block, stmt), returnTemp(BAD_VAR_NUM) { } @@ -540,26 +538,23 @@ class IndirectCallTransformer checkBlock = currBlock; checkBlock->bbJumpKind = BBJ_COND; - CallArg* thisArg = origCall->gtArgs.GetThisArg(); - GenTree* thisTree = thisArg->GetNode(); + // Fetch method table from object arg to call. + GenTree* thisTree = compiler->gtCloneExpr(origCall->gtArgs.GetThisArg()->GetNode()); // Create temp for this if the tree is costly. - if (thisTree->IsLocal()) - { - thisTree = compiler->gtCloneExpr(thisTree); - } - else + if (!thisTree->IsLocal()) { const unsigned thisTempNum = compiler->lvaGrabTemp(true DEBUGARG("guarded devirt this temp")); - GenTree* asgTree = compiler->gtNewTempAssign(thisTempNum, thisTree); - Statement* asgStmt = compiler->fgNewStmtFromTree(asgTree, stmt->GetDebugInfo()); + // lvaSetClass(thisTempNum, ...); + GenTree* asgTree = compiler->gtNewTempAssign(thisTempNum, thisTree); + Statement* asgStmt = compiler->fgNewStmtFromTree(asgTree, stmt->GetDebugInfo()); compiler->fgInsertStmtAtEnd(checkBlock, asgStmt); thisTree = compiler->gtNewLclvNode(thisTempNum, TYP_REF); // Propagate the new this to the call. Must be a new expr as the call // will live on in the else block and thisTree is used below. - thisArg->SetEarlyNode(compiler->gtNewLclvNode(thisTempNum, TYP_REF)); + origCall->gtArgs.GetThisArg()->SetEarlyNode(compiler->gtNewLclvNode(thisTempNum, TYP_REF)); } // Remember the current last statement. If we're doing a chained GDV, we'll clone/copy @@ -570,96 +565,18 @@ class IndirectCallTransformer // lastStmt = checkBlock->lastStmt(); - GuardedDevirtualizationCandidateInfo* guardedInfo = origCall->gtGuardedDevirtualizationCandidateInfo; - - // Create comparison. On success we will jump to do the indirect call. - GenTree* compare; - if (guardedInfo->guardedClassHandle != NO_CLASS_HANDLE) - { - // Find target method table - // - GenTree* methodTable = compiler->gtNewMethodTableLookup(thisTree); - CORINFO_CLASS_HANDLE clsHnd = guardedInfo->guardedClassHandle; - GenTree* targetMethodTable = compiler->gtNewIconEmbClsHndNode(clsHnd); - - compare = compiler->gtNewOperNode(GT_NE, TYP_INT, targetMethodTable, methodTable); - } - else - { - assert(origCall->IsVirtualVtable() || origCall->IsDelegateInvoke()); - // We reuse the target except if this is a chained GDV, in - // which case the check will be moved into the success case of - // a previous GDV and thus may not execute when we hit the cold - // path. - // TODO-GDV: Consider duplicating the store at the end of the - // cold case for the previous GDV. Then we can reuse the target - // if the second check of a chained GDV fails. - bool reuseTarget = (origCall->gtCallMoreFlags & GTF_CALL_M_GUARDED_DEVIRT_CHAIN) == 0; - if (origCall->IsVirtualVtable()) - { - GenTree* tarTree = compiler->fgExpandVirtualVtableCallTarget(origCall); - - if (reuseTarget) - { - m_targetLclNum = compiler->lvaGrabTemp(false DEBUGARG("guarded devirt call target temp")); - - GenTree* asgTree = compiler->gtNewTempAssign(m_targetLclNum, tarTree); - Statement* asgStmt = compiler->fgNewStmtFromTree(asgTree, stmt->GetDebugInfo()); - compiler->fgInsertStmtAtEnd(checkBlock, asgStmt); - - tarTree = compiler->gtNewLclvNode(m_targetLclNum, TYP_I_IMPL); - } - - CORINFO_METHOD_HANDLE methHnd = guardedInfo->guardedMethodHandle; - CORINFO_CONST_LOOKUP lookup; - compiler->info.compCompHnd->getFunctionEntryPoint(methHnd, &lookup); - - GenTree* compareTarTree = CreateTreeForLookup(methHnd, lookup); - compare = compiler->gtNewOperNode(GT_NE, TYP_INT, compareTarTree, tarTree); - } - else - { - // Reusing the call target for delegates is more - // complicated. Essentially we need to do the - // transformation done in LowerDelegateInvoke by converting - // the call to CT_INDIRECT and reusing the target address. - // We will do that transformation in CreateElse, but here - // we need to stash the target. - CLANG_FORMAT_COMMENT_ANCHOR; -#ifdef TARGET_ARM - // Not impossible to support, but would additionally - // require us to load the wrapper delegate cell when - // expanding. - reuseTarget &= (origCall->gtCallMoreFlags & GTF_CALL_M_WRAPPER_DELEGATE_INV) == 0; -#endif - - GenTree* offset = - compiler->gtNewIconNode((ssize_t)compiler->eeGetEEInfo()->offsetOfDelegateFirstTarget, - TYP_I_IMPL); - GenTree* tarTree = compiler->gtNewOperNode(GT_ADD, TYP_BYREF, thisTree, offset); - tarTree = compiler->gtNewIndir(TYP_I_IMPL, tarTree); - - if (reuseTarget) - { - m_targetLclNum = compiler->lvaGrabTemp(false DEBUGARG("guarded devirt call target temp")); - - GenTree* asgTree = compiler->gtNewTempAssign(m_targetLclNum, tarTree); - Statement* asgStmt = compiler->fgNewStmtFromTree(asgTree, stmt->GetDebugInfo()); - compiler->fgInsertStmtAtEnd(checkBlock, asgStmt); - tarTree = compiler->gtNewLclvNode(m_targetLclNum, TYP_I_IMPL); - } - - CORINFO_METHOD_HANDLE methHnd = guardedInfo->guardedMethodHandle; - CORINFO_CONST_LOOKUP lookup; - compiler->info.compCompHnd->getFunctionFixedEntryPoint(methHnd, false, &lookup); - - GenTree* compareTarTree = CreateTreeForLookup(methHnd, lookup); - compare = compiler->gtNewOperNode(GT_NE, TYP_INT, compareTarTree, tarTree); - } - } + // Find target method table + // + GenTree* methodTable = compiler->gtNewMethodTableLookup(thisTree); + GuardedDevirtualizationCandidateInfo* guardedInfo = origCall->gtGuardedDevirtualizationCandidateInfo; + CORINFO_CLASS_HANDLE clsHnd = guardedInfo->guardedClassHandle; + GenTree* targetMethodTable = compiler->gtNewIconEmbClsHndNode(clsHnd); - GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, compare); - Statement* jmpStmt = compiler->fgNewStmtFromTree(jmpTree, stmt->GetDebugInfo()); + // Compare and jump to else (which does the indirect call) if NOT equal + // + GenTree* methodTableCompare = compiler->gtNewOperNode(GT_NE, TYP_INT, targetMethodTable, methodTable); + GenTree* jmpTree = compiler->gtNewOperNode(GT_JTRUE, TYP_VOID, methodTableCompare); + Statement* jmpStmt = compiler->fgNewStmtFromTree(jmpTree, stmt->GetDebugInfo()); compiler->fgInsertStmtAtEnd(checkBlock, jmpStmt); } @@ -765,94 +682,35 @@ class IndirectCallTransformer InlineCandidateInfo* inlineInfo = origCall->gtInlineCandidateInfo; CORINFO_CLASS_HANDLE clsHnd = inlineInfo->guardedClassHandle; - // - // Copy the 'this' for the devirtualized call to a new temp. For - // class-based GDV this will allow us to set the exact type on that - // temp. For delegate GDV, this will be the actual 'this' object - // stored in the delegate. - // + // copy 'this' to temp with exact type. const unsigned thisTemp = compiler->lvaGrabTemp(false DEBUGARG("guarded devirt this exact temp")); GenTree* clonedObj = compiler->gtCloneExpr(origCall->gtArgs.GetThisArg()->GetNode()); - GenTree* newThisObj; - if (origCall->IsDelegateInvoke()) - { - GenTree* offset = - compiler->gtNewIconNode((ssize_t)compiler->eeGetEEInfo()->offsetOfDelegateInstance, TYP_I_IMPL); - newThisObj = compiler->gtNewOperNode(GT_ADD, TYP_BYREF, clonedObj, offset); - newThisObj = compiler->gtNewIndir(TYP_REF, newThisObj); - } - else - { - newThisObj = clonedObj; - } - GenTree* assign = compiler->gtNewTempAssign(thisTemp, newThisObj); - - if (clsHnd != NO_CLASS_HANDLE) - { - compiler->lvaSetClass(thisTemp, clsHnd, true); - } - else - { - compiler->lvaSetClass(thisTemp, - compiler->info.compCompHnd->getMethodClass(inlineInfo->guardedMethodHandle)); - } - + GenTree* assign = compiler->gtNewTempAssign(thisTemp, clonedObj); + compiler->lvaSetClass(thisTemp, clsHnd, true); compiler->fgNewStmtAtEnd(thenBlock, assign); - // Clone call for the devirtualized case. Note we must use the - // special candidate helper and we need to use the new 'this'. + // Clone call. Note we must use the special candidate helper. GenTreeCall* call = compiler->gtCloneCandidateCall(origCall); call->gtArgs.GetThisArg()->SetEarlyNode(compiler->gtNewLclvNode(thisTemp, TYP_REF)); call->SetIsGuarded(); JITDUMP("Direct call [%06u] in block " FMT_BB "\n", compiler->dspTreeID(call), thenBlock->bbNum); - CORINFO_METHOD_HANDLE methodHnd = call->gtCallMethHnd; - CORINFO_CONTEXT_HANDLE context = inlineInfo->exactContextHnd; - if (clsHnd != NO_CLASS_HANDLE) - { - // Then invoke impDevirtualizeCall to actually transform the call for us, - // given the original (base) method and the exact guarded class. It should succeed. - // - unsigned methodFlags = compiler->info.compCompHnd->getMethodAttribs(methodHnd); - const bool isLateDevirtualization = true; - const bool explicitTailCall = (call->AsCall()->gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0; - compiler->impDevirtualizeCall(call, nullptr, &methodHnd, &methodFlags, &context, nullptr, - isLateDevirtualization, explicitTailCall); - } - else - { - // Otherwise we know the exact method already, so just change - // the call as necessary here. - call->gtFlags &= ~GTF_CALL_VIRT_KIND_MASK; - call->gtCallMethHnd = methodHnd = inlineInfo->guardedMethodHandle; - call->gtCallType = CT_USER_FUNC; - call->gtCallMoreFlags |= GTF_CALL_M_DEVIRTUALIZED; - call->gtCallMoreFlags &= ~GTF_CALL_M_DELEGATE_INV; - // TODO-GDV: To support R2R we need to get the entry point - // here. We should unify with the tail of impDevirtualizeCall. - - if (origCall->IsVirtual()) - { - // Virtual calls include an implicit null check, which we may - // now need to make explicit. - bool isExact; - bool objIsNonNull; - compiler->gtGetClassHandle(newThisObj, &isExact, &objIsNonNull); - - if (!objIsNonNull) - { - call->gtFlags |= GTF_CALL_NULLCHECK; - } - } - - context = MAKE_METHODCONTEXT(methodHnd); - } + // Then invoke impDevirtualizeCall to actually transform the call for us, + // given the original (base) method and the exact guarded class. It should succeed. + // + CORINFO_METHOD_HANDLE methodHnd = call->gtCallMethHnd; + unsigned methodFlags = compiler->info.compCompHnd->getMethodAttribs(methodHnd); + CORINFO_CONTEXT_HANDLE context = inlineInfo->exactContextHnd; + const bool isLateDevirtualization = true; + const bool explicitTailCall = (call->AsCall()->gtCallMoreFlags & GTF_CALL_M_EXPLICIT_TAILCALL) != 0; + compiler->impDevirtualizeCall(call, nullptr, &methodHnd, &methodFlags, &context, nullptr, + isLateDevirtualization, explicitTailCall); // We know this call can devirtualize or we would not have set up GDV here. - // So above code should succeed in devirtualizing. + // So impDevirtualizeCall should succeed in devirtualizing. // - assert(!call->IsVirtual() && !call->IsDelegateInvoke()); + assert(!call->IsVirtual()); // If the devirtualizer was unable to transform the call to invoke the unboxed entry, the inline info // we set up may be invalid. We won't be able to inline anyways. So demote the call as an inline candidate. @@ -918,7 +776,7 @@ class IndirectCallTransformer } //------------------------------------------------------------------------ - // CreateElse: create else block. This executes the original indirect call. + // CreateElse: create else block. This executes the unaltered indirect call. // virtual void CreateElse() { @@ -938,38 +796,6 @@ class IndirectCallTransformer newStmt->SetRootNode(assign); } - if (m_targetLclNum != BAD_VAR_NUM) - { - if (call->IsVirtualVtable()) - { - // We already loaded the target once for the check, so reuse it from the temp. - call->gtControlExpr = compiler->gtNewLclvNode(m_targetLclNum, TYP_I_IMPL); - call->SetExpandedEarly(); - } - else if (call->IsDelegateInvoke()) - { - // Target was saved into a temp during check. We expand the - // delegate call to a CT_INDIRECT call that uses the target - // directly, somewhat similarly to LowerDelegateInvoke. - call->gtCallType = CT_INDIRECT; - call->gtCallAddr = compiler->gtNewLclvNode(m_targetLclNum, TYP_I_IMPL); - call->gtCallCookie = nullptr; - call->gtCallMoreFlags &= ~GTF_CALL_M_DELEGATE_INV; - - GenTree* thisOffset = - compiler->gtNewIconNode((ssize_t)compiler->eeGetEEInfo()->offsetOfDelegateInstance, TYP_I_IMPL); - CallArg* thisArg = call->gtArgs.GetThisArg(); - GenTree* delegateObj = thisArg->GetNode(); - - assert(delegateObj->OperIsLocal()); - GenTree* newThis = - compiler->gtNewOperNode(GT_ADD, TYP_BYREF, compiler->gtCloneExpr(delegateObj), thisOffset); - newThis = compiler->gtNewIndir(TYP_REF, newThis); - - thisArg->SetEarlyNode(newThis); - } - } - compiler->fgInsertStmtAtEnd(elseBlock, newStmt); // Set the original statement to a nop. @@ -1179,62 +1005,6 @@ class IndirectCallTransformer private: unsigned returnTemp; Statement* lastStmt; - - //------------------------------------------------------------------------ - // CreateTreeForLookup: Create a tree representing a lookup of a method address. - // - // Arguments: - // methHnd - the handle for the method the lookup is for - // lookup - lookup information for the address - // - // Returns: - // A node representing the lookup. - // - GenTree* CreateTreeForLookup(CORINFO_METHOD_HANDLE methHnd, const CORINFO_CONST_LOOKUP& lookup) - { - switch (lookup.accessType) - { - case IAT_VALUE: - { - return CreateFunctionTargetAddr(methHnd, lookup); - } - case IAT_PVALUE: - { - GenTree* tree = CreateFunctionTargetAddr(methHnd, lookup); - tree = compiler->gtNewIndir(TYP_I_IMPL, tree); - tree->gtFlags |= GTF_IND_NONFAULTING | GTF_IND_INVARIANT; - tree->gtFlags &= ~GTF_EXCEPT; - return tree; - } - case IAT_PPVALUE: - { - noway_assert(!"Unexpected IAT_PPVALUE"); - return nullptr; - } - case IAT_RELPVALUE: - { - GenTree* addr = CreateFunctionTargetAddr(methHnd, lookup); - GenTree* tree = CreateFunctionTargetAddr(methHnd, lookup); - tree = compiler->gtNewIndir(TYP_I_IMPL, tree); - tree->gtFlags |= GTF_IND_NONFAULTING | GTF_IND_INVARIANT; - tree->gtFlags &= ~GTF_EXCEPT; - tree = compiler->gtNewOperNode(GT_ADD, TYP_I_IMPL, tree, addr); - return tree; - } - default: - { - noway_assert(!"Bad accessType"); - return nullptr; - } - } - } - - GenTree* CreateFunctionTargetAddr(CORINFO_METHOD_HANDLE methHnd, const CORINFO_CONST_LOOKUP& lookup) - { - GenTree* con = compiler->gtNewIconHandleNode((size_t)lookup.addr, GTF_ICON_FTN_ADDR); - INDEBUG(con->AsIntCon()->gtTargetHandle = (size_t)methHnd); - return con; - } }; // Runtime lookup with dynamic dictionary expansion transformer, diff --git a/src/coreclr/jit/inline.cpp b/src/coreclr/jit/inline.cpp index 7f3c65fde97ff..546eb2aa376f9 100644 --- a/src/coreclr/jit/inline.cpp +++ b/src/coreclr/jit/inline.cpp @@ -643,8 +643,7 @@ void InlineContext::DumpXml(FILE* file, unsigned indent) // stmt - statement containing the call (if known) // description - string describing the context of the decision -InlineResult::InlineResult( - Compiler* compiler, GenTreeCall* call, Statement* stmt, const char* description, bool doNotReport) +InlineResult::InlineResult(Compiler* compiler, GenTreeCall* call, Statement* stmt, const char* description) : m_RootCompiler(nullptr) , m_Policy(nullptr) , m_Call(call) @@ -653,9 +652,7 @@ InlineResult::InlineResult( , m_Callee(nullptr) , m_ImportedILSize(0) , m_Description(description) - , m_successResult(INLINE_PASS) - , m_DoNotReport(doNotReport) - , m_reportFailureAsVmFailure(false) + , m_Reported(false) { // Set the compiler instance m_RootCompiler = compiler->impInlineRoot(); @@ -686,12 +683,6 @@ InlineResult::InlineResult( { m_Callee = m_Call->AsCall()->gtCallMethHnd; } - - if (!m_DoNotReport) - { - COMP_HANDLE comp = m_RootCompiler->info.compCompHnd; - comp->beginInlining(m_Caller, m_Callee); - } } //------------------------------------------------------------------------ @@ -710,7 +701,7 @@ InlineResult::InlineResult( // We use the inlCallee member to track the method since logically // it is the callee here. -InlineResult::InlineResult(Compiler* compiler, CORINFO_METHOD_HANDLE method, const char* description, bool doNotReport) +InlineResult::InlineResult(Compiler* compiler, CORINFO_METHOD_HANDLE method, const char* description) : m_RootCompiler(nullptr) , m_Policy(nullptr) , m_Call(nullptr) @@ -718,9 +709,7 @@ InlineResult::InlineResult(Compiler* compiler, CORINFO_METHOD_HANDLE method, con , m_Caller(nullptr) , m_Callee(method) , m_Description(description) - , m_successResult(INLINE_PASS) - , m_DoNotReport(doNotReport) - , m_reportFailureAsVmFailure(false) + , m_Reported(false) { // Set the compiler instance m_RootCompiler = compiler->impInlineRoot(); @@ -728,12 +717,6 @@ InlineResult::InlineResult(Compiler* compiler, CORINFO_METHOD_HANDLE method, con // Set the policy const bool isPrejitRoot = true; m_Policy = InlinePolicy::GetPolicy(m_RootCompiler, isPrejitRoot); - - if (!m_DoNotReport) - { - COMP_HANDLE comp = m_RootCompiler->info.compCompHnd; - comp->beginInlining(m_Caller, m_Callee); - } } //------------------------------------------------------------------------ @@ -748,6 +731,8 @@ InlineResult::InlineResult(Compiler* compiler, CORINFO_METHOD_HANDLE method, con // EE. Optionally update the method attribute to NOINLINE if // observation and policy warrant. // +// All this can be suppressed if desired by calling setReported() +// before the InlineResult goes out of scope. void InlineResult::Report() { @@ -768,13 +753,13 @@ void InlineResult::Report() #endif // DEBUG // If we weren't actually inlining, user may have suppressed - // reporting. If so, do nothing. - if (m_DoNotReport) + // reporting via setReported(). If so, do nothing. + if (m_Reported) { return; } - m_DoNotReport = true; + m_Reported = true; #ifdef DEBUG const char* callee = nullptr; @@ -813,7 +798,7 @@ void InlineResult::Report() } } - if (IsDecided() || m_reportFailureAsVmFailure || m_successResult != INLINE_PASS) + if (IsDecided()) { const char* format = "INLINER: during '%s' result '%s' reason '%s'\n"; JITLOG_THIS(m_RootCompiler, (LL_INFO100000, format, m_Description, ResultString(), ReasonString())); diff --git a/src/coreclr/jit/inline.h b/src/coreclr/jit/inline.h index f21a77da4fa14..e5ec2ea3cc10e 100644 --- a/src/coreclr/jit/inline.h +++ b/src/coreclr/jit/inline.h @@ -344,12 +344,11 @@ class InlineResult public: // Construct a new InlineResult to help evaluate a // particular call for inlining. - InlineResult( - Compiler* compiler, GenTreeCall* call, Statement* stmt, const char* description, bool doNotReport = false); + InlineResult(Compiler* compiler, GenTreeCall* call, Statement* stmt, const char* description); // Construct a new InlineResult to evaluate a particular // method to see if it is inlineable. - InlineResult(Compiler* compiler, CORINFO_METHOD_HANDLE method, const char* description, bool doNotReport = false); + InlineResult(Compiler* compiler, CORINFO_METHOD_HANDLE method, const char* description); // Has the policy determined this inline should fail? bool IsFailure() const @@ -484,42 +483,18 @@ class InlineResult // Result that can be reported back to the runtime CorInfoInline Result() const { - if (m_reportFailureAsVmFailure) - return INLINE_CHECK_CAN_INLINE_VMFAIL; - - if (m_successResult != INLINE_PASS) - return m_successResult; - return InlGetCorInfoInlineDecision(m_Policy->GetDecision()); } // String describing the decision made const char* ResultString() const { - if (m_reportFailureAsVmFailure) - return "VM Reported !CanInline"; - - if (m_successResult == INLINE_PREJIT_SUCCESS) - return "PreJIT Success"; - - if (m_successResult == INLINE_CHECK_CAN_INLINE_SUCCESS) - return "CheckCanInline Success"; - return InlGetDecisionString(m_Policy->GetDecision()); } // String describing the reason for the decision const char* ReasonString() const { - if (m_reportFailureAsVmFailure) - return "VM Reported !CanInline"; - - if (m_successResult == INLINE_PREJIT_SUCCESS) - return "PreJIT Success"; - - if (m_successResult == INLINE_CHECK_CAN_INLINE_SUCCESS) - return "CheckCanInline Success"; - return InlGetObservationString(m_Policy->GetObservation()); } @@ -529,15 +504,12 @@ class InlineResult return m_Policy; } - // Set the code that shall be reported if the InlineResult is a success - void SetSuccessResult(CorInfoInline inlineSuccessCode) - { - m_successResult = inlineSuccessCode; - } - - void SetVMFailure() + // SetReported indicates that this particular result doesn't need + // to be reported back to the runtime, either because the runtime + // already knows, or we aren't actually inlining yet. + void SetReported() { - m_reportFailureAsVmFailure = true; + m_Reported = true; } // Get the InlineContext for this inline. @@ -572,15 +544,13 @@ class InlineResult CORINFO_METHOD_HANDLE m_Callee; unsigned m_ImportedILSize; // estimated size of imported IL const char* m_Description; - CorInfoInline m_successResult; - bool m_DoNotReport; - bool m_reportFailureAsVmFailure; + bool m_Reported; }; -// HandleHistogramProfileCandidateInfo provides information about +// ClassProfileCandidateInfo provides information about // profiling an indirect or virtual call. // -struct HandleHistogramProfileCandidateInfo +struct ClassProfileCandidateInfo { IL_OFFSET ilOffset; unsigned probeIndex; @@ -589,7 +559,7 @@ struct HandleHistogramProfileCandidateInfo // GuardedDevirtualizationCandidateInfo provides information about // a potential target of a virtual or interface call. // -struct GuardedDevirtualizationCandidateInfo : HandleHistogramProfileCandidateInfo +struct GuardedDevirtualizationCandidateInfo : ClassProfileCandidateInfo { CORINFO_CLASS_HANDLE guardedClassHandle; CORINFO_METHOD_HANDLE guardedMethodHandle; diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h index e766df67304d8..0a8527a6393fe 100644 --- a/src/coreclr/jit/instrsxarch.h +++ b/src/coreclr/jit/instrsxarch.h @@ -594,8 +594,8 @@ INST3(LAST_AVXVNNI_INSTRUCTION, "LAST_AVXVNNI_INSTRUCTION", IUM_WR, BAD_CODE, BA // BMI1 INST3(FIRST_BMI_INSTRUCTION, "FIRST_BMI_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, BAD_CODE, INS_FLAGS_None) INST3(andn, "andn", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF2), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Resets_CF | INS_Flags_IsDstDstSrcAVXInstruction) // Logical AND NOT -INST3(blsi, "blsi", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_IsDstDstSrcAVXInstruction) // Extract Lowest Set Isolated Bit -INST3(blsmsk, "blsmsk", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Resets_CF | INS_Flags_IsDstDstSrcAVXInstruction) // Get Mask Up to Lowest Set Bit +INST3(blsi, "blsi", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_IsDstDstSrcAVXInstruction) // Extract Lowest Set Isolated Bit +INST3(blsmsk, "blsmsk", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), INS_Flags_IsDstDstSrcAVXInstruction) // Get Mask Up to Lowest Set Bit INST3(blsr, "blsr", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF3), Resets_OF | Writes_SF | Writes_ZF | Undefined_AF | Undefined_PF | Writes_CF | INS_Flags_IsDstDstSrcAVXInstruction) // Reset Lowest Set Bit INST3(bextr, "bextr", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0xF7), INS_Flags_IsDstDstSrcAVXInstruction) // Bit Field Extract diff --git a/src/coreclr/jit/jit.h b/src/coreclr/jit/jit.h index 110c079ee58c4..d4ea7ab0dcb91 100644 --- a/src/coreclr/jit/jit.h +++ b/src/coreclr/jit/jit.h @@ -327,9 +327,8 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX typedef class ICorJitInfo* COMP_HANDLE; -const CORINFO_CLASS_HANDLE NO_CLASS_HANDLE = nullptr; -const CORINFO_FIELD_HANDLE NO_FIELD_HANDLE = nullptr; -const CORINFO_METHOD_HANDLE NO_METHOD_HANDLE = nullptr; +const CORINFO_CLASS_HANDLE NO_CLASS_HANDLE = nullptr; +const CORINFO_FIELD_HANDLE NO_FIELD_HANDLE = nullptr; /*****************************************************************************/ @@ -337,8 +336,7 @@ typedef unsigned IL_OFFSET; const IL_OFFSET BAD_IL_OFFSET = 0xffffffff; -const unsigned BAD_VAR_NUM = UINT_MAX; -const uint16_t BAD_LCL_OFFSET = UINT16_MAX; +const unsigned BAD_VAR_NUM = UINT_MAX; // Code can't be more than 2^31 in any direction. This is signed, so it should be used for anything that is // relative to something else. @@ -840,26 +838,19 @@ T dspOffset(T o) #endif // !defined(DEBUG) -struct LikelyClassMethodRecord +struct LikelyClassRecord { - intptr_t handle; - UINT32 likelihood; + CORINFO_CLASS_HANDLE clsHandle; + UINT32 likelihood; }; -extern "C" UINT32 WINAPI getLikelyClasses(LikelyClassMethodRecord* pLikelyClasses, +extern "C" UINT32 WINAPI getLikelyClasses(LikelyClassRecord* pLikelyClasses, UINT32 maxLikelyClasses, ICorJitInfo::PgoInstrumentationSchema* schema, UINT32 countSchemaItems, BYTE* pInstrumentationData, int32_t ilOffset); -extern "C" UINT32 WINAPI getLikelyMethods(LikelyClassMethodRecord* pLikelyMethods, - UINT32 maxLikelyMethods, - ICorJitInfo::PgoInstrumentationSchema* schema, - UINT32 countSchemaItems, - BYTE* pInstrumentationData, - int32_t ilOffset); - /*****************************************************************************/ #endif //_JIT_H_ /*****************************************************************************/ diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 9ae04f0505953..0d701bb958ce3 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -354,9 +354,9 @@ CONFIG_INTEGER(JitDisableSimdVN, W("JitDisableSimdVN"), 0) // Default 0, ValueNu // CONFIG_INTEGER(JitConstCSE, W("JitConstCSE"), 0) -#define CONST_CSE_ENABLE_ARM 0 +#define CONST_CSE_ENABLE_ARM64 0 #define CONST_CSE_DISABLE_ALL 1 -#define CONST_CSE_ENABLE_ARM_NO_SHARING 2 +#define CONST_CSE_ENABLE_ARM64_NO_SHARING 2 #define CONST_CSE_ENABLE_ALL 3 #define CONST_CSE_ENABLE_ALL_NO_SHARING 4 @@ -548,12 +548,10 @@ CONFIG_INTEGER(JitMinimalJitProfiling, W("JitMinimalJitProfiling"), 1) CONFIG_INTEGER(JitMinimalPrejitProfiling, W("JitMinimalPrejitProfiling"), 0) CONFIG_INTEGER(JitProfileCasts, W("JitProfileCasts"), 0) // Profile castclass/isinst -CONFIG_INTEGER(JitConsumeProfileForCasts, W("JitConsumeProfileForCasts"), 1) // Consume profile data (if any) for +CONFIG_INTEGER(JitConsumeProfileForCasts, W("JitConsumeProfileForCasts"), 0) // Consume profile data (if any) for // castclass/isinst CONFIG_INTEGER(JitClassProfiling, W("JitClassProfiling"), 1) // Profile virtual and interface calls -CONFIG_INTEGER(JitDelegateProfiling, W("JitDelegateProfiling"), 1) // Profile resolved delegate call targets -CONFIG_INTEGER(JitVTableProfiling, W("JitVTableProfiling"), 0) // Profile resolved vtable call targets CONFIG_INTEGER(JitEdgeProfiling, W("JitEdgeProfiling"), 1) // Profile edges instead of blocks CONFIG_INTEGER(JitCollect64BitCounts, W("JitCollect64BitCounts"), 0) // Collect counts as 64-bit values. @@ -605,8 +603,6 @@ CONFIG_STRING(JitFunctionFile, W("JitFunctionFile")) // 1: disable frames that save FP/LR registers with the callee-saved registers (at the top of the frame) // 2: force all frames to use the frame types that save FP/LR registers with the callee-saved registers (at the top // of the frame) -// 3: force all frames to use the frame types that save FP/LR registers with the callee-saved registers (at the top -// of the frame) and also force using the large funclet frame variation (frame 5) if possible. CONFIG_INTEGER(JitSaveFpLrWithCalleeSavedRegisters, W("JitSaveFpLrWithCalleeSavedRegisters"), 0) #endif // defined(TARGET_ARM64) diff --git a/src/coreclr/jit/lclmorph.cpp b/src/coreclr/jit/lclmorph.cpp index 4ca754e9c993b..25074f8827472 100644 --- a/src/coreclr/jit/lclmorph.cpp +++ b/src/coreclr/jit/lclmorph.cpp @@ -836,10 +836,10 @@ class LocalAddressVisitor final : public GenTreeVisitor LclVarDsc* varDsc = m_compiler->lvaGetDesc(val.LclNum()); - if (varDsc->lvPromoted || varDsc->lvIsStructField) + if (varDsc->lvPromoted || varDsc->lvIsStructField || m_compiler->lvaIsImplicitByRefLocal(val.LclNum())) { - // TODO-ADDR: For now we ignore promoted variables, they require - // additional changes in subsequent phases. + // TODO-ADDR: For now we ignore promoted and "implicit by ref" variables, + // they require additional changes in subsequent phases. return; } @@ -1017,10 +1017,11 @@ class LocalAddressVisitor final : public GenTreeVisitor return IndirTransform::None; } - if (varDsc->lvPromoted || varDsc->lvIsStructField) + if (varDsc->lvPromoted || varDsc->lvIsStructField || m_compiler->lvaIsImplicitByRefLocal(val.LclNum())) { - // TODO-ADDR: For now we ignore promoted variables, they require additional - // changes in subsequent phases. + // TODO-ADDR: For now we ignore promoted and "implicit by ref" variables, + // they require additional changes in subsequent phases + // (e.g. fgMorphImplicitByRefArgs does not handle LCL_FLD nodes). return IndirTransform::None; } @@ -1036,6 +1037,7 @@ class LocalAddressVisitor final : public GenTreeVisitor { // TODO-ADDR: Skip SIMD indirs for now, SIMD typed LCL_FLDs works most of the time // but there are exceptions - fgMorphFieldAssignToSimdSetElement for example. + // And more importantly, SIMD call args have to be wrapped in OBJ nodes currently. return IndirTransform::None; } @@ -1048,9 +1050,10 @@ class LocalAddressVisitor final : public GenTreeVisitor return IndirTransform::None; } - if ((user == nullptr) || !user->OperIs(GT_ASG, GT_CALL, GT_RETURN)) + if ((user == nullptr) || !user->OperIs(GT_ASG, GT_RETURN)) { - // TODO-ADDR: remove unused indirections. + // TODO-ADDR: call args require extra work because currently they must + // be wrapped in OBJ nodes so we can't replace those with local nodes. return IndirTransform::None; } @@ -1073,6 +1076,7 @@ class LocalAddressVisitor final : public GenTreeVisitor // enum class StructMatch { + Exact, Compatible, Partial }; @@ -1081,49 +1085,49 @@ class LocalAddressVisitor final : public GenTreeVisitor assert(varDsc->GetLayout() != nullptr); StructMatch match = StructMatch::Partial; - if ((val.Offset() == 0) && ClassLayout::AreCompatible(indirLayout, varDsc->GetLayout())) + if (val.Offset() == 0) { - match = StructMatch::Compatible; + if (indirLayout->GetClassHandle() == varDsc->GetStructHnd()) + { + match = StructMatch::Exact; + } + else if (ClassLayout::AreCompatible(indirLayout, varDsc->GetLayout())) + { + match = StructMatch::Compatible; + } } // Current matrix of matches/users/types: // - // |------------|---------|-------------|---------| - // | STRUCT | CALL(*) | ASG | RETURN | - // |------------|---------|-------------|---------| - // | Compatible | LCL_VAR | LCL_VAR | LCL_VAR | - // | Partial | LCL_FLD | OBJ/LCL_FLD | LCL_FLD | - // |------------|---------|-------------|---------| - // - // * - On x86/Windows x64 only. + // |------------|------|---------|---------| + // | STRUCT | CALL | ASG | RETURN | + // |------------|------|---------|---------| + // | Exact | None | LCL_VAR | LCL_VAR | + // | Compatible | None | LCL_VAR | LCL_VAR | + // | Partial | None | OBJ | LCL_FLD | + // |------------|------|---------|---------| // - // |------------|------|------|--------|----------| - // | SIMD | CALL | ASG | RETURN | HWI/SIMD | - // |------------|------|------|--------|----------| - // | Compatible | None | None | None | None | - // | Partial | None | None | None | None | - // |------------|------|------|--------|----------| + // |------------|------|---------|---------|----------| + // | SIMD | CALL | ASG | RETURN | HWI/SIMD | + // |------------|------|---------|---------|----------| + // | Exact | None | None | None | None | + // | Compatible | None | None | None | None | + // | Partial | None | None | None | None | + // |------------|------|---------|---------|----------| // // TODO-ADDR: delete all the "None" entries and always // transform local nodes into LCL_VAR or LCL_FLD. - assert(indir->TypeIs(TYP_STRUCT) && user->OperIs(GT_ASG, GT_CALL, GT_RETURN)); + assert(indir->TypeIs(TYP_STRUCT) && user->OperIs(GT_ASG, GT_RETURN)); *pStructLayout = indirLayout; - if (user->IsCall()) - { -#if !defined(WINDOWS_AMD64_ABI) && !defined(TARGET_X86) - return IndirTransform::None; -#endif // !defined(WINDOWS_AMD64_ABI) && !defined(TARGET_X86) - } - - if (match == StructMatch::Compatible) + if ((match == StructMatch::Exact) || (match == StructMatch::Compatible)) { return IndirTransform::LclVar; } - if (user->OperIs(GT_ASG) && (indir == user->AsOp()->gtGetOp1())) + if (user->OperIs(GT_ASG)) { return IndirTransform::ObjAddrLclFld; } diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index a1439c7e4bd5c..cc12c8a3837da 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1494,14 +1494,14 @@ void Compiler::lvaInitVarDsc(LclVarDsc* varDsc, varDsc->lvOverlappingFields = StructHasOverlappingFields(cFlags); } -#if FEATURE_IMPLICIT_BYREFS +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) varDsc->lvIsImplicitByRef = 0; -#endif // FEATURE_IMPLICIT_BYREFS -#ifdef TARGET_LOONGARCH64 - varDsc->lvIs4Field1 = 0; - varDsc->lvIs4Field2 = 0; - varDsc->lvIsSplit = 0; -#endif // TARGET_LOONGARCH64 +#elif defined(TARGET_LOONGARCH64) + varDsc->lvIsImplicitByRef = 0; + varDsc->lvIs4Field1 = 0; + varDsc->lvIs4Field2 = 0; + varDsc->lvIsSplit = 0; +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Set the lvType (before this point it is TYP_UNDEF). @@ -1832,7 +1832,7 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE const int MaxOffset = MAX_NumOfFieldsInPromotableStruct * FP_REGSIZE_BYTES; #endif // defined(TARGET_XARCH) || defined(TARGET_ARM64) #else // !FEATURE_SIMD - const int MaxOffset = MAX_NumOfFieldsInPromotableStruct * sizeof(double); + const int MaxOffset = MAX_NumOfFieldsInPromotableStruct * sizeof(double); #endif // !FEATURE_SIMD assert((BYTE)MaxOffset == MaxOffset); // because lvaStructFieldInfo.fldOffset is byte-sized @@ -2535,10 +2535,12 @@ void Compiler::StructPromotionHelper::PromoteStructVar(unsigned lclNum) compiler->compLongUsed = true; } -#if FEATURE_IMPLICIT_BYREFS +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + // Reset the implicitByRef flag. fieldVarDsc->lvIsImplicitByRef = 0; -#endif // FEATURE_IMPLICIT_BYREFS + +#endif // Do we have a parameter that can be enregistered? // @@ -2888,61 +2890,6 @@ void Compiler::lvaSetVarDoNotEnregister(unsigned varNum DEBUGARG(DoNotEnregister #endif } -//------------------------------------------------------------------------ -// lvaIsImplicitByRefLocal: Is the local an "implicit byref" parameter? -// -// We term structs passed via pointers to shadow copies "implicit byrefs". -// They are used on Windows x64 for structs 3, 5, 6, 7, > 8 bytes in size, -// and on ARM64/LoongArch64 for structs larger than 16 bytes. -// -// They are "byrefs" because the VM sometimes uses memory allocated on the -// GC heap for the shadow copies. -// -// Arguments: -// lclNum - The local in question -// -// Return Value: -// Whether "lclNum" refers to an implicit byref. -// -bool Compiler::lvaIsImplicitByRefLocal(unsigned lclNum) const -{ -#if FEATURE_IMPLICIT_BYREFS - LclVarDsc* varDsc = lvaGetDesc(lclNum); - if (varDsc->lvIsImplicitByRef) - { - assert(varDsc->lvIsParam); - - assert(varTypeIsStruct(varDsc) || (varDsc->TypeGet() == TYP_BYREF)); - return true; - } -#endif // FEATURE_IMPLICIT_BYREFS - return false; -} - -//------------------------------------------------------------------------ -// lvaIsLocalImplicitlyAccessedByRef: Will this local be accessed indirectly? -// -// Arguments: -// lclNum - The number of local in question -// -// Return Value: -// If "lclNum" is an implicit byref parameter, or its dependently promoted -// field, "true", otherwise, "false". -// -// Notes: -// This method is only meaningful before the locals have been morphed into -// explicit indirections. -// -bool Compiler::lvaIsLocalImplicitlyAccessedByRef(unsigned lclNum) const -{ - if (lvaGetDesc(lclNum)->lvIsStructField) - { - return lvaIsImplicitByRefLocal(lvaGetDesc(lclNum)->lvParentLcl); - } - - return lvaIsImplicitByRefLocal(lclNum); -} - // Returns true if this local var is a multireg struct. // TODO-Throughput: This does a lookup on the class handle, and in the outgoing arg context // this information is already available on the CallArgABIInformation, and shouldn't need to be @@ -3004,7 +2951,7 @@ void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool CorInfoType simdBaseJitType = CORINFO_TYPE_UNDEF; varDsc->lvType = impNormStructType(typeHnd, &simdBaseJitType); -#if FEATURE_IMPLICIT_BYREFS +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Mark implicit byref struct parameters if (varDsc->lvIsParam && !varDsc->lvIsStructField) { @@ -3017,7 +2964,7 @@ void Compiler::lvaSetStruct(unsigned varNum, CORINFO_CLASS_HANDLE typeHnd, bool varDsc->lvIsImplicitByRef = 1; } } -#endif // FEATURE_IMPLICIT_BYREFS +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) #if FEATURE_SIMD if (simdBaseJitType != CORINFO_TYPE_UNDEF) @@ -4234,57 +4181,49 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, /* Is this an assignment to a local variable? */ - if (op1->gtOper == GT_LCL_VAR) + if (op1->gtOper == GT_LCL_VAR && op2->gtType != TYP_BOOL) { - LclVarDsc* varDsc = lvaGetDesc(op1->AsLclVarCommon()); + /* Only simple assignments allowed for booleans */ - if (varDsc->lvPinned && varDsc->lvAllDefsAreNoGc) + if (tree->gtOper != GT_ASG) { - if (!op2->IsNotGcDef()) - { - varDsc->lvAllDefsAreNoGc = false; - } + goto NOT_BOOL; } - if (op2->gtType != TYP_BOOL) - { - /* Only simple assignments allowed for booleans */ + /* Is the RHS clearly a boolean value? */ - if (tree->gtOper != GT_ASG) - { - goto NOT_BOOL; - } + switch (op2->gtOper) + { + unsigned lclNum; - /* Is the RHS clearly a boolean value? */ + case GT_CNS_INT: - switch (op2->gtOper) - { - case GT_CNS_INT: + if (op2->AsIntCon()->gtIconVal == 0) + { + break; + } + if (op2->AsIntCon()->gtIconVal == 1) + { + break; + } - if (op2->AsIntCon()->gtIconVal == 0) - { - break; - } - if (op2->AsIntCon()->gtIconVal == 1) - { - break; - } + // Not 0 or 1, fall through .... + FALLTHROUGH; - // Not 0 or 1, fall through .... - FALLTHROUGH; + default: - default: + if (op2->OperIsCompare()) + { + break; + } - if (op2->OperIsCompare()) - { - break; - } + NOT_BOOL: - NOT_BOOL: + lclNum = op1->AsLclVarCommon()->GetLclNum(); + noway_assert(lclNum < lvaCount); - varDsc->lvIsBoolean = false; - break; - } + lvaTable[lclNum].lvIsBoolean = false; + break; } } } @@ -4339,8 +4278,7 @@ void Compiler::lvaMarkLclRefs(GenTree* tree, BasicBlock* block, Statement* stmt, { if (lvaVarAddrExposed(lclNum)) { - varDsc->lvIsBoolean = false; - varDsc->lvAllDefsAreNoGc = false; + varDsc->lvIsBoolean = false; } if (tree->gtOper == GT_LCL_FLD) @@ -4812,8 +4750,6 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) { varDsc->lvSingleDef = varDsc->lvIsParam; varDsc->lvSingleDefRegCandidate = varDsc->lvIsParam; - - varDsc->lvAllDefsAreNoGc = (varDsc->lvImplicitlyReferenced == false); } } @@ -4932,13 +4868,6 @@ void Compiler::lvaComputeRefCounts(bool isRecompute, bool setSlotNumbers) varDsc->lvImplicitlyReferenced = 1; } } - - if (varDsc->lvPinned && varDsc->lvAllDefsAreNoGc) - { - varDsc->lvPinned = 0; - - JITDUMP("V%02u was unpinned as all def candidates were local.\n", lclNum); - } } } @@ -6403,7 +6332,7 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() { codeGen->SetSaveFpLrWithAllCalleeSavedRegisters(false); // Disable using new frames } - else if ((opts.compJitSaveFpLrWithCalleeSavedRegisters == 2) || (opts.compJitSaveFpLrWithCalleeSavedRegisters == 3)) + else if (opts.compJitSaveFpLrWithCalleeSavedRegisters == 2) { codeGen->SetSaveFpLrWithAllCalleeSavedRegisters(true); // Force using new frames } diff --git a/src/coreclr/jit/likelyclass.cpp b/src/coreclr/jit/likelyclass.cpp index 6943c0c5a83a9..632c9ce8b847b 100644 --- a/src/coreclr/jit/likelyclass.cpp +++ b/src/coreclr/jit/likelyclass.cpp @@ -26,45 +26,45 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Data item in class profile histogram // -struct LikelyClassMethodHistogramEntry +struct LikelyClassHistogramEntry { - // Handle that was observed at runtime - INT_PTR m_handle; // This may be an "unknown handle" + // Class that was observed at runtime + INT_PTR m_mt; // This may be an "unknown type handle" // Number of observations in the table unsigned m_count; }; // Summarizes a ClassProfile table by forming a Histogram // -struct LikelyClassMethodHistogram +struct LikelyClassHistogram { - LikelyClassMethodHistogram(INT_PTR* histogramEntries, unsigned entryCount); + LikelyClassHistogram(INT_PTR* histogramEntries, unsigned entryCount); // Sum of counts from all entries in the histogram. This includes "unknown" entries which are not captured in // m_histogram unsigned m_totalCount; - // Rough guess at count of unknown handles - unsigned m_unknownHandles; + // Rough guess at count of unknown types + unsigned m_unknownTypes; // Histogram entries, in no particular order. - LikelyClassMethodHistogramEntry m_histogram[HISTOGRAM_MAX_SIZE_COUNT]; - UINT32 countHistogramElements = 0; + LikelyClassHistogramEntry m_histogram[HISTOGRAM_MAX_SIZE_COUNT]; + UINT32 countHistogramElements = 0; - LikelyClassMethodHistogramEntry HistogramEntryAt(unsigned index) + LikelyClassHistogramEntry HistogramEntryAt(unsigned index) { return m_histogram[index]; } }; //------------------------------------------------------------------------ -// LikelyClassMethodHistogram::LikelyClassMethodHistgram: construct a new histogram +// LikelyClassHistogram::LikelyClassHistgram: construct a new histogram // // Arguments: // histogramEntries - pointer to the table portion of a ClassProfile* object (see corjit.h) // entryCount - number of entries in the table to examine // -LikelyClassMethodHistogram::LikelyClassMethodHistogram(INT_PTR* histogramEntries, unsigned entryCount) +LikelyClassHistogram::LikelyClassHistogram(INT_PTR* histogramEntries, unsigned entryCount) { - m_unknownHandles = 0; + m_unknownTypes = 0; m_totalCount = 0; uint32_t unknownTypeHandleMask = 0; @@ -83,7 +83,7 @@ LikelyClassMethodHistogram::LikelyClassMethodHistogram(INT_PTR* histogramEntries unsigned h = 0; for (; h < countHistogramElements; h++) { - if (m_histogram[h].m_handle == currentEntry) + if (m_histogram[h].m_mt == currentEntry) { m_histogram[h].m_count++; found = true; @@ -97,8 +97,8 @@ LikelyClassMethodHistogram::LikelyClassMethodHistogram(INT_PTR* histogramEntries { continue; } - LikelyClassMethodHistogramEntry newEntry; - newEntry.m_handle = currentEntry; + LikelyClassHistogramEntry newEntry; + newEntry.m_mt = currentEntry; newEntry.m_count = 1; m_histogram[countHistogramElements++] = newEntry; } @@ -106,28 +106,42 @@ LikelyClassMethodHistogram::LikelyClassMethodHistogram(INT_PTR* histogramEntries } //------------------------------------------------------------------------ -// getLikelyClassesOrMethods: -// Find class/method profile data for an IL offset, and return the most -// likely classes/methods. +// getLikelyClasses: find class profile data for an IL offset, and return the most likely classes +// +// Arguments: +// pLikelyClasses - [OUT] array of likely classes sorted by likelihood (descending). It must be +// at least of 'maxLikelyClasses' (next argument) length. +// The array consists of pairs "clsHandle - likelihood" ordered by likelihood +// (descending) where likelihood can be any value in [0..100] range. clsHandle +// is never null for [0..) range, Items in +// [..maxLikelyClasses) are zeroed if the number +// of classes seen is less than maxLikelyClasses provided. +// maxLikelyClasses - limit for likely classes to output +// schema - profile schema +// countSchemaItems - number of items in the schema +// pInstrumentationData - associated data +// ilOffset - il offset of the callvirt // -// This is a common entrypoint for getLikelyClasses and getLikelyMethods. -// See documentation for those for more information. +// Returns: +// Estimated number of classes seen at runtime +// +// Notes: +// A "monomorphic" call site will return likelihood 100 and number of entries = 1. +// +// This is used by the devirtualization logic below, and by crossgen2 when producing +// the R2R image (to reduce the sizecost of carrying the type histogram) +// +// This code can runs without a jit instance present, so JITDUMP and related +// cannot be used. // -static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* pLikelyEntries, - UINT32 maxLikelyClasses, - ICorJitInfo::PgoInstrumentationSchema* schema, - UINT32 countSchemaItems, - BYTE* pInstrumentationData, - int32_t ilOffset, - bool types) +extern "C" DLLEXPORT UINT32 WINAPI getLikelyClasses(LikelyClassRecord* pLikelyClasses, + UINT32 maxLikelyClasses, + ICorJitInfo::PgoInstrumentationSchema* schema, + UINT32 countSchemaItems, + BYTE* pInstrumentationData, + int32_t ilOffset) { - ICorJitInfo::PgoInstrumentationKind histogramKind = - types ? ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes - : ICorJitInfo::PgoInstrumentationKind::HandleHistogramMethods; - ICorJitInfo::PgoInstrumentationKind compressedKind = types ? ICorJitInfo::PgoInstrumentationKind::GetLikelyClass - : ICorJitInfo::PgoInstrumentationKind::GetLikelyMethod; - - memset(pLikelyEntries, 0, maxLikelyClasses * sizeof(*pLikelyEntries)); + ZeroMemory(pLikelyClasses, maxLikelyClasses * sizeof(*pLikelyClasses)); if (schema == nullptr) { @@ -139,16 +153,17 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* if (schema[i].ILOffset != ilOffset) continue; - if ((schema[i].InstrumentationKind == compressedKind) && (schema[i].Count == 1)) + if ((schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::GetLikelyClass) && + (schema[i].Count == 1)) { - intptr_t result = *(intptr_t*)(pInstrumentationData + schema[i].Offset); + INT_PTR result = *(INT_PTR*)(pInstrumentationData + schema[i].Offset); if (ICorJitInfo::IsUnknownHandle(result)) { return 0; } - assert(result != 0); // we don't expect zero in GetLikelyClass/GetLikelyMethod - pLikelyEntries[0].likelihood = (UINT32)(schema[i].Other & 0xFF); - pLikelyEntries[0].handle = result; + assert(result != 0); // we don't expect zero in GetLikelyClass + pLikelyClasses[0].likelihood = (UINT32)(schema[i].Other & 0xFF); + pLikelyClasses[0].clsHandle = (CORINFO_CLASS_HANDLE)result; return 1; } @@ -157,11 +172,11 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* (schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramLongCount); if (isHistogramCount && (schema[i].Count == 1) && ((i + 1) < countSchemaItems) && - (schema[i + 1].InstrumentationKind == histogramKind)) + (schema[i + 1].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes)) { // Form a histogram // - LikelyClassMethodHistogram h((INT_PTR*)(pInstrumentationData + schema[i + 1].Offset), schema[i + 1].Count); + LikelyClassHistogram h((INT_PTR*)(pInstrumentationData + schema[i + 1].Offset), schema[i + 1].Count); // Use histogram count as number of classes estimate // Report back what we've learned @@ -174,45 +189,45 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* case 1: { - LikelyClassMethodHistogramEntry const hist0 = h.HistogramEntryAt(0); + LikelyClassHistogramEntry const hist0 = h.HistogramEntryAt(0); // Fast path for monomorphic cases - if (ICorJitInfo::IsUnknownHandle(hist0.m_handle)) + if (ICorJitInfo::IsUnknownHandle(hist0.m_mt)) { return 0; } - pLikelyEntries[0].likelihood = 100; - pLikelyEntries[0].handle = hist0.m_handle; + pLikelyClasses[0].likelihood = 100; + pLikelyClasses[0].clsHandle = (CORINFO_CLASS_HANDLE)hist0.m_mt; return 1; } case 2: { + LikelyClassHistogramEntry const hist0 = h.HistogramEntryAt(0); + LikelyClassHistogramEntry const hist1 = h.HistogramEntryAt(1); // Fast path for two classes - LikelyClassMethodHistogramEntry const hist0 = h.HistogramEntryAt(0); - LikelyClassMethodHistogramEntry const hist1 = h.HistogramEntryAt(1); - if ((hist0.m_count >= hist1.m_count) && !ICorJitInfo::IsUnknownHandle(hist0.m_handle)) + if ((hist0.m_count >= hist1.m_count) && !ICorJitInfo::IsUnknownHandle(hist0.m_mt)) { - pLikelyEntries[0].likelihood = (100 * hist0.m_count) / h.m_totalCount; - pLikelyEntries[0].handle = hist0.m_handle; + pLikelyClasses[0].likelihood = (100 * hist0.m_count) / h.m_totalCount; + pLikelyClasses[0].clsHandle = (CORINFO_CLASS_HANDLE)hist0.m_mt; - if ((maxLikelyClasses > 1) && !ICorJitInfo::IsUnknownHandle(hist1.m_handle)) + if ((maxLikelyClasses > 1) && !ICorJitInfo::IsUnknownHandle(hist1.m_mt)) { - pLikelyEntries[1].likelihood = (100 * hist1.m_count) / h.m_totalCount; - pLikelyEntries[1].handle = hist1.m_handle; + pLikelyClasses[1].likelihood = (100 * hist1.m_count) / h.m_totalCount; + pLikelyClasses[1].clsHandle = (CORINFO_CLASS_HANDLE)hist1.m_mt; return 2; } return 1; } - if (!ICorJitInfo::IsUnknownHandle(hist1.m_handle)) + if (!ICorJitInfo::IsUnknownHandle(hist1.m_mt)) { - pLikelyEntries[0].likelihood = (100 * hist1.m_count) / h.m_totalCount; - pLikelyEntries[0].handle = hist1.m_handle; + pLikelyClasses[0].likelihood = (100 * hist1.m_count) / h.m_totalCount; + pLikelyClasses[0].clsHandle = (CORINFO_CLASS_HANDLE)hist1.m_mt; - if ((maxLikelyClasses > 1) && !ICorJitInfo::IsUnknownHandle(hist0.m_handle)) + if ((maxLikelyClasses > 1) && !ICorJitInfo::IsUnknownHandle(hist0.m_mt)) { - pLikelyEntries[1].likelihood = (100 * hist0.m_count) / h.m_totalCount; - pLikelyEntries[1].handle = hist0.m_handle; + pLikelyClasses[1].likelihood = (100 * hist0.m_count) / h.m_totalCount; + pLikelyClasses[1].clsHandle = (CORINFO_CLASS_HANDLE)hist0.m_mt; return 2; } return 1; @@ -222,14 +237,14 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* default: { - LikelyClassMethodHistogramEntry sortedEntries[HISTOGRAM_MAX_SIZE_COUNT]; + LikelyClassHistogramEntry sortedEntries[HISTOGRAM_MAX_SIZE_COUNT]; // Since this method can be invoked without a jit instance we can't use any existing allocators unsigned knownHandles = 0; for (unsigned m = 0; m < h.countHistogramElements; m++) { - LikelyClassMethodHistogramEntry const hist = h.HistogramEntryAt(m); - if (!ICorJitInfo::IsUnknownHandle(hist.m_handle)) + LikelyClassHistogramEntry const hist = h.HistogramEntryAt(m); + if (!ICorJitInfo::IsUnknownHandle(hist.m_mt)) { sortedEntries[knownHandles++] = hist; } @@ -237,8 +252,7 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* // sort by m_count (descending) jitstd::sort(sortedEntries, sortedEntries + knownHandles, - [](const LikelyClassMethodHistogramEntry& h1, - const LikelyClassMethodHistogramEntry& h2) -> bool { + [](const LikelyClassHistogramEntry& h1, const LikelyClassHistogramEntry& h2) -> bool { return h1.m_count > h2.m_count; }); @@ -246,9 +260,9 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* for (size_t hIdx = 0; hIdx < numberOfClasses; hIdx++) { - LikelyClassMethodHistogramEntry const hc = sortedEntries[hIdx]; - pLikelyEntries[hIdx].handle = hc.m_handle; - pLikelyEntries[hIdx].likelihood = hc.m_count * 100 / h.m_totalCount; + LikelyClassHistogramEntry const hc = sortedEntries[hIdx]; + pLikelyClasses[hIdx].clsHandle = (CORINFO_CLASS_HANDLE)hc.m_mt; + pLikelyClasses[hIdx].likelihood = hc.m_count * 100 / h.m_totalCount; } return numberOfClasses; } @@ -262,57 +276,80 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* } //------------------------------------------------------------------------ -// getLikelyClasses: find class profile data for an IL offset, and return the most likely classes +// getRandomClass: find class profile data for an IL offset, and return +// one of the possible classes at random // // Arguments: -// pLikelyClasses - [OUT] array of likely classes sorted by likelihood (descending). It must be -// at least of 'maxLikelyClasses' (next argument) length. -// The array consists of pairs "clsHandle - likelihood" ordered by likelihood -// (descending) where likelihood can be any value in [0..100] range. clsHandle -// is never null for [0..) range, Items in -// [..maxLikelyClasses) are zeroed if the number -// of classes seen is less than maxLikelyClasses provided. -// maxLikelyClasses - limit for likely classes to output // schema - profile schema // countSchemaItems - number of items in the schema // pInstrumentationData - associated data // ilOffset - il offset of the callvirt +// random - randomness generator // // Returns: -// Estimated number of classes seen at runtime -// -// Notes: -// A "monomorphic" call site will return likelihood 100 and number of entries = 1. -// -// This is used by the devirtualization logic below, and by crossgen2 when producing -// the R2R image (to reduce the sizecost of carrying the type histogram) -// -// This code can runs without a jit instance present, so JITDUMP and related -// cannot be used. +// Randomly observed class, or nullptr. // -extern "C" DLLEXPORT UINT32 WINAPI getLikelyClasses(LikelyClassMethodRecord* pLikelyClasses, - UINT32 maxLikelyClasses, - ICorJitInfo::PgoInstrumentationSchema* schema, - UINT32 countSchemaItems, - BYTE* pInstrumentationData, - int32_t ilOffset) +CORINFO_CLASS_HANDLE Compiler::getRandomClass(ICorJitInfo::PgoInstrumentationSchema* schema, + UINT32 countSchemaItems, + BYTE* pInstrumentationData, + int32_t ilOffset, + CLRRandom* random) { - return getLikelyClassesOrMethods(pLikelyClasses, maxLikelyClasses, schema, countSchemaItems, pInstrumentationData, - ilOffset, true); -} + if (schema == nullptr) + { + return NO_CLASS_HANDLE; + } -//------------------------------------------------------------------------ -// getLikelyMethods: find method profile data for an IL offset, and return the most likely methods -// -// See documentation on getLikelyClasses above. -// -extern "C" DLLEXPORT UINT32 WINAPI getLikelyMethods(LikelyClassMethodRecord* pLikelyMethods, - UINT32 maxLikelyMethods, - ICorJitInfo::PgoInstrumentationSchema* schema, - UINT32 countSchemaItems, - BYTE* pInstrumentationData, - int32_t ilOffset) -{ - return getLikelyClassesOrMethods(pLikelyMethods, maxLikelyMethods, schema, countSchemaItems, pInstrumentationData, - ilOffset, false); + for (COUNT_T i = 0; i < countSchemaItems; i++) + { + if (schema[i].ILOffset != (int32_t)ilOffset) + { + continue; + } + + if ((schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::GetLikelyClass) && + (schema[i].Count == 1)) + { + INT_PTR result = *(INT_PTR*)(pInstrumentationData + schema[i].Offset); + if (ICorJitInfo::IsUnknownHandle(result)) + { + return NO_CLASS_HANDLE; + } + else + { + return (CORINFO_CLASS_HANDLE)result; + } + } + + bool isHistogramCount = + (schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramIntCount) || + (schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramLongCount); + + if (isHistogramCount && (schema[i].Count == 1) && ((i + 1) < countSchemaItems) && + (schema[i + 1].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes)) + { + // Form a histogram + // + LikelyClassHistogram h((INT_PTR*)(pInstrumentationData + schema[i + 1].Offset), schema[i + 1].Count); + + if (h.countHistogramElements == 0) + { + return NO_CLASS_HANDLE; + } + + // Choose an entry at random. + // + unsigned randomEntryIndex = random->Next(0, h.countHistogramElements); + LikelyClassHistogramEntry randomEntry = h.HistogramEntryAt(randomEntryIndex); + + if (ICorJitInfo::IsUnknownHandle(randomEntry.m_mt)) + { + return NO_CLASS_HANDLE; + } + + return (CORINFO_CLASS_HANDLE)randomEntry.m_mt; + } + } + + return NO_CLASS_HANDLE; } diff --git a/src/coreclr/jit/loopcloning.cpp b/src/coreclr/jit/loopcloning.cpp index 05c96837bc4ef..915f19525ffc8 100644 --- a/src/coreclr/jit/loopcloning.cpp +++ b/src/coreclr/jit/loopcloning.cpp @@ -1724,25 +1724,6 @@ bool Compiler::optIsLoopClonable(unsigned loopInd) return false; } - // Reject cloning if this is a mid-entry loop and the entry has non-loop predecessors other than its head. - // This loop may be part of a larger looping construct that we didn't recognize. - // - // We should really fix this in optCanonicalizeLoop. - // - if (!loop.lpIsTopEntry()) - { - for (BasicBlock* const entryPred : loop.lpEntry->PredBlocks()) - { - if ((entryPred != loop.lpHead) && !loop.lpContains(entryPred)) - { - JITDUMP("Loop cloning: rejecting loop " FMT_LP - ". Is not top entry, and entry has multiple non-loop preds.\n", - loopInd); - return false; - } - } - } - // We've previously made a decision whether to have separate return epilogs, or branch to one. // There's a GCInfo limitation in the x86 case, so that there can be no more than SET_EPILOGCNT_MAX separate // epilogs. Other architectures have a limit of 4 here for "historical reasons", but this should be revisited diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 0450beb2b2607..98bd11f0fd2d3 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -388,6 +388,16 @@ GenTree* Lowering::LowerNode(GenTree* node) break; #endif +#if !defined(TARGET_ARMARCH) && !defined(TARGET_LOONGARCH64) + // TODO-ARMARCH-CQ: We should contain this as long as the offset fits. + case GT_OBJ: + if (node->AsObj()->Addr()->OperIsLocalAddr()) + { + node->AsObj()->Addr()->SetContained(); + } + break; +#endif // !TARGET_ARMARCH + case GT_KEEPALIVE: node->gtGetOp1()->SetRegOptional(); break; @@ -1013,6 +1023,7 @@ bool Lowering::TryLowerSwitchToBitTest( GenTree* bitTest = comp->gtNewOperNode(GT_BT, TYP_VOID, bitTableIcon, switchValue); bitTest->gtFlags |= GTF_SET_FLAGS; GenTreeCC* jcc = new (comp, GT_JCC) GenTreeCC(GT_JCC, bbSwitchCondition); + jcc->gtFlags |= GTF_USE_FLAGS; LIR::AsRange(bbSwitch).InsertAfter(switchValue, bitTableIcon, bitTest, jcc); @@ -1020,6 +1031,9 @@ bool Lowering::TryLowerSwitchToBitTest( #endif // TARGET_XARCH } +// NOTE: this method deliberately does not update the call arg table. It must only +// be used by NewPutArg and LowerArg; these functions are responsible for updating +// the call arg table as necessary. void Lowering::ReplaceArgWithPutArgOrBitcast(GenTree** argSlot, GenTree* putArgOrBitcast) { assert(argSlot != nullptr); @@ -1055,7 +1069,12 @@ void Lowering::ReplaceArgWithPutArgOrBitcast(GenTree** argSlot, GenTree* putArgO // Notes: // For System V systems with native struct passing (i.e. UNIX_AMD64_ABI defined) // this method allocates a single GT_PUTARG_REG for 1 eightbyte structs and a GT_FIELD_LIST of two GT_PUTARG_REGs -// for two eightbyte structs. For STK passed structs the method generates GT_PUTARG_STK tree. +// for two eightbyte structs. +// +// For STK passed structs the method generates GT_PUTARG_STK tree. For System V systems with native struct passing +// (i.e. UNIX_AMD64_ABI defined) this method also sets the GC pointers count and the pointers +// layout object, so the codegen of the GT_PUTARG_STK could use this for optimizing copying to the stack by value. +// (using block copy primitives for non GC pointers and a single TARGET_POINTER_SIZE copy with recording GC info.) // GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, var_types type) { @@ -1067,6 +1086,19 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, bool isOnStack = (callArg->AbiInfo.GetRegNum() == REG_STK); +#if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) + // Mark contained when we pass struct + // GT_FIELD_LIST is always marked contained when it is generated + if (type == TYP_STRUCT) + { + arg->SetContained(); + if ((arg->OperGet() == GT_OBJ) && (arg->AsObj()->Addr()->OperGet() == GT_LCL_VAR_ADDR)) + { + MakeSrcContained(arg, arg->AsObj()->Addr()); + } + } +#endif + #if FEATURE_ARG_SPLIT // Struct can be split into register(s) and stack on ARM if (compFeatureArgSplit() && callArg->AbiInfo.IsSplit()) @@ -1088,7 +1120,10 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, callArg->AbiInfo.GetStackByteSize(), #endif callArg->AbiInfo.NumRegs, call, putInIncomingArgArea); - + // If struct argument is morphed to GT_FIELD_LIST node(s), + // we can know GC info by type of each GT_FIELD_LIST node. + // So we skip setting GC Pointer info. + // GenTreePutArgSplit* argSplit = putArg->AsPutArgSplit(); for (unsigned regIndex = 0; regIndex < callArg->AbiInfo.NumRegs; regIndex++) { @@ -1097,12 +1132,6 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, if (arg->OperGet() == GT_OBJ) { - arg->SetContained(); - if (arg->AsObj()->Addr()->OperGet() == GT_LCL_VAR_ADDR) - { - MakeSrcContained(arg, arg->AsObj()->Addr()); - } - ClassLayout* layout = arg->AsObj()->GetLayout(); // Set type of registers @@ -1177,6 +1206,8 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, #ifdef DEBUG // Make sure state is correct. The PUTARG_STK has TYP_VOID, as it doesn't produce // a result. So the type of its operand must be the correct type to push on the stack. + // For a FIELD_LIST, this will be the type of the field (not the type of the arg), + // but otherwise it is generally the type of the operand. callArg->CheckIsStruct(); #endif @@ -1214,15 +1245,64 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, #endif call, putInIncomingArgArea); -#if defined(DEBUG) && defined(FEATURE_PUT_STRUCT_ARG_STK) +#ifdef FEATURE_PUT_STRUCT_ARG_STK + // If the ArgTabEntry indicates that this arg is a struct + // get and store the number of slots that are references. + // This is later used in the codegen for PUT_ARG_STK implementation + // for struct to decide whether and how many single eight-byte copies + // to be done (only for reference slots), so gcinfo is emitted. + // For non-reference slots faster/smaller size instructions are used - + // pair copying using XMM registers or rep mov instructions. if (callArg->AbiInfo.IsStruct) { - // We use GT_OBJ only for non-SIMD struct arguments. - if (arg->OperIs(GT_OBJ)) + // We use GT_OBJ only for non-lclVar, non-SIMD, non-FIELD_LIST struct arguments. + if (arg->OperIsLocal()) + { + // This must have a type with a known size (SIMD or has been morphed to a primitive type). + assert(arg->TypeGet() != TYP_STRUCT); + } + else if (arg->OperIs(GT_OBJ)) { assert(!varTypeIsSIMD(arg)); + +#ifdef TARGET_X86 + // On x86 VM lies about the type of a struct containing a pointer sized + // integer field by returning the type of its field as the type of struct. + // Such struct can be passed in a register depending its position in + // parameter list. VM does this unwrapping only one level and therefore + // a type like Struct Foo { Struct Bar { int f}} awlays needs to be + // passed on stack. Also, VM doesn't lie about type of such a struct + // when it is a field of another struct. That is VM doesn't lie about + // the type of Foo.Bar + // + // We now support the promotion of fields that are of type struct. + // However we only support a limited case where the struct field has a + // single field and that single field must be a scalar type. Say Foo.Bar + // field is getting passed as a parameter to a call, Since it is a TYP_STRUCT, + // as per x86 ABI it should always be passed on stack. Therefore GenTree + // node under a PUTARG_STK could be GT_OBJ(GT_LCL_VAR_ADDR(v1)), where + // local v1 could be a promoted field standing for Foo.Bar. Note that + // the type of v1 will be the type of field of Foo.Bar.f when Foo is + // promoted. That is v1 will be a scalar type. In this case we need to + // pass v1 on stack instead of in a register. + // + // TODO-PERF: replace GT_OBJ(GT_LCL_VAR_ADDR(v1)) with v1 if v1 is + // a scalar type and the width of GT_OBJ matches the type size of v1. + // Note that this cannot be done till call node arguments are morphed + // because we should not lose the fact that the type of argument is + // a struct so that the arg gets correctly marked to be passed on stack. + GenTree* objOp1 = arg->gtGetOp1(); + if (objOp1->OperGet() == GT_LCL_VAR_ADDR) + { + unsigned lclNum = objOp1->AsLclVarCommon()->GetLclNum(); + if (comp->lvaTable[lclNum].lvType != TYP_STRUCT) + { + comp->lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::VMNeedsStackAddr)); + } + } +#endif // TARGET_X86 } - else if (!arg->TypeIs(TYP_STRUCT)) + else if (!arg->OperIs(GT_FIELD_LIST)) { #ifdef TARGET_ARM assert((callArg->AbiInfo.GetStackSlotsNumber() == 1) || @@ -1232,7 +1312,7 @@ GenTree* Lowering::NewPutArg(GenTreeCall* call, GenTree* arg, CallArg* callArg, #endif } } -#endif // defined(DEBUG) && defined(FEATURE_PUT_STRUCT_ARG_STK) +#endif // FEATURE_PUT_STRUCT_ARG_STK } } @@ -1379,13 +1459,6 @@ void Lowering::LowerArg(GenTreeCall* call, CallArg* callArg, bool late) ReplaceArgWithPutArgOrBitcast(ppArg, putArg); } } - - arg = *ppArg; - - if (arg->OperIs(GT_PUTARG_STK)) - { - LowerPutArgStk(arg->AsPutArgStk()); - } } #if defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64) @@ -2210,58 +2283,10 @@ void Lowering::LowerCFGCall(GenTreeCall* call) } GenTree* callTarget = call->gtCallType == CT_INDIRECT ? call->gtCallAddr : call->gtControlExpr; - if (callTarget == nullptr) - { - assert((call->gtCallType != CT_INDIRECT) && (!call->IsVirtual() || call->IsVirtualStubRelativeIndir())); - if (!call->IsVirtual()) - { - // Direct call with stashed address - return; - } - - // This is a VSD call with the call target being null because we are - // supposed to load it from the indir cell. Due to CFG we will need - // this address twice, and at least on ARM64 we do not want to - // materialize the constant both times. - CallArg* indirCellArg = call->gtArgs.FindWellKnownArg(WellKnownArg::VirtualStubCell); - assert((indirCellArg != nullptr) && indirCellArg->GetNode()->OperIs(GT_PUTARG_REG)); - - GenTreeOp* putArgNode = indirCellArg->GetNode()->AsOp(); - LIR::Use indirCellArgUse(BlockRange(), &putArgNode->gtOp1, putArgNode); - - // On non-xarch, we create a local even for constants. On xarch cloning - // the constant is better since it can be contained in the load below. - bool cloneConsts = false; -#ifdef TARGET_XARCH - cloneConsts = true; -#endif - - GenTree* indirCellClone; - - if (indirCellArgUse.Def()->OperIs(GT_LCL_VAR) || (cloneConsts && indirCellArgUse.Def()->IsCnsIntOrI())) - { - indirCellClone = comp->gtClone(indirCellArgUse.Def()); - } - else - { - unsigned newLcl = indirCellArgUse.ReplaceWithLclVar(comp); - indirCellClone = comp->gtNewLclvNode(newLcl, TYP_I_IMPL); - } - - callTarget = Ind(indirCellClone); - LIR::Range controlExprRange = LIR::SeqTree(comp, callTarget); - ContainCheckRange(controlExprRange); - - BlockRange().InsertBefore(call, std::move(controlExprRange)); - call->gtControlExpr = callTarget; - } - else + if ((callTarget == nullptr) || callTarget->IsIntegralConst()) { - if (callTarget->IsIntegralConst()) - { - // This is a direct call, no CFG check is necessary. - return; - } + // This is a direct call, no CFG check is necessary. + return; } CFGCallKind cfgKind = call->GetCFGCallKind(); @@ -2702,6 +2727,7 @@ GenTree* Lowering::DecomposeLongCompare(GenTree* cmp) GenTree* jcc = cmpUse.User(); jcc->AsOp()->gtOp1 = nullptr; jcc->ChangeOper(GT_JCC); + jcc->gtFlags |= GTF_USE_FLAGS; jcc->AsCC()->gtCondition = GenCondition::FromIntegralRelop(condition, cmp->IsUnsigned()); } else @@ -2709,6 +2735,7 @@ GenTree* Lowering::DecomposeLongCompare(GenTree* cmp) cmp->AsOp()->gtOp1 = nullptr; cmp->AsOp()->gtOp2 = nullptr; cmp->ChangeOper(GT_SETCC); + cmp->gtFlags |= GTF_USE_FLAGS; cmp->AsCC()->gtCondition = GenCondition::FromIntegralRelop(condition, cmp->IsUnsigned()); } @@ -2956,6 +2983,8 @@ GenTree* Lowering::OptimizeConstCompare(GenTree* cmp) cmpUse.ReplaceWith(cc); } + cc->gtFlags |= GTF_USE_FLAGS; + return cmp->gtNext; } #endif // TARGET_XARCH @@ -3023,6 +3052,7 @@ GenTree* Lowering::OptimizeConstCompare(GenTree* cmp) GenCondition condition = GenCondition::FromIntegralRelop(cmp); cc->ChangeOper(ccOp); cc->AsCC()->gtCondition = condition; + cc->gtFlags |= GTF_USE_FLAGS; return next; } @@ -3240,6 +3270,7 @@ GenTreeCC* Lowering::LowerNodeCC(GenTree* node, GenCondition condition) if (cc != nullptr) { node->gtFlags |= GTF_SET_FLAGS; + cc->gtFlags |= GTF_USE_FLAGS; } // Remove the chain of EQ/NE(x, 0) relop nodes, if any. Note that if a SETCC was @@ -3508,13 +3539,13 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore) // Do it now. GenTreeIndir* indir = src->AsIndir(); LowerIndir(indir); - } #if defined(TARGET_XARCH) - if (varTypeIsSmall(lclRegType)) - { - src->SetDontExtend(); - } + if (varTypeIsSmall(lclRegType)) + { + indir->SetDontExtend(); + } #endif // TARGET_XARCH + } } convertToStoreObj = false; #else // TARGET_ARM64 @@ -3783,18 +3814,18 @@ void Lowering::LowerCallStruct(GenTreeCall* call) if (GlobalJitOptions::compFeatureHfa) { - if (comp->IsHfa(call->gtRetClsHnd)) + if (comp->IsHfa(call)) { #if defined(TARGET_ARM64) - assert(comp->GetHfaCount(call->gtRetClsHnd) == 1); + assert(comp->GetHfaCount(call) == 1); #elif defined(TARGET_ARM) // ARM returns double in 2 float registers, but // `call->HasMultiRegRetVal()` count double registers. - assert(comp->GetHfaCount(call->gtRetClsHnd) <= 2); + assert(comp->GetHfaCount(call) <= 2); #else // !TARGET_ARM64 && !TARGET_ARM NYI("Unknown architecture"); #endif // !TARGET_ARM64 && !TARGET_ARM - var_types hfaType = comp->GetHfaType(call->gtRetClsHnd); + var_types hfaType = comp->GetHfaType(call); if (call->TypeIs(hfaType)) { return; @@ -5096,7 +5127,7 @@ GenTree* Lowering::LowerVirtualStubCall(GenTreeCall* call) // Skip inserting the indirection node to load the address that is already // computed in the VSD stub arg register as a hidden parameter. Instead during the // codegen, just load the call target from there. - shouldOptimizeVirtualStubCall = true; + shouldOptimizeVirtualStubCall = !comp->opts.IsCFGEnabled(); #endif if (!shouldOptimizeVirtualStubCall) @@ -5364,7 +5395,7 @@ bool Lowering::TryCreateAddrMode(GenTree* addr, bool isContainable, GenTree* par // Check if we can "contain" LEA(BFIZ) in order to extend 32bit index to 64bit as part of load/store. if ((index != nullptr) && index->OperIs(GT_BFIZ) && index->gtGetOp1()->OperIs(GT_CAST) && - index->gtGetOp2()->IsCnsIntOrI() && !varTypeIsStruct(targetType)) + index->gtGetOp2()->IsCnsIntOrI() && (varTypeIsIntegral(targetType) || varTypeIsFloating(targetType))) { // BFIZ node is a binary op where op1 is GT_CAST and op2 is GT_CNS_INT GenTreeCast* cast = index->gtGetOp1()->AsCast(); @@ -5807,8 +5838,7 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node) #if defined(TARGET_ARM64) if (divMod->OperIs(GT_MOD) && divisor->IsIntegralConstPow2()) { - LowerModPow2(node); - return node->gtNext; + return LowerModPow2(node); } assert(node->OperGet() != GT_MOD); #endif // TARGET_ARM64 @@ -7344,9 +7374,9 @@ bool Lowering::TryTransformStoreObjAsStoreInd(GenTreeBlk* blkNode) } #if defined(TARGET_XARCH) - if (varTypeIsSmall(regType) && src->OperIs(GT_IND, GT_LCL_FLD)) + if (varTypeIsSmall(regType) && src->OperIs(GT_IND)) { - src->SetDontExtend(); + src->AsIndir()->SetDontExtend(); } #endif // TARGET_XARCH @@ -7384,7 +7414,6 @@ void Lowering::LowerSIMD(GenTreeSIMD* simdNode) if (arg->IsCnsFltOrDbl()) { - noway_assert(constArgCount < ArrLen(constArgValues)); constArgValues[constArgCount] = static_cast(arg->AsDblCon()->gtDconVal); constArgCount++; } @@ -7397,14 +7426,10 @@ void Lowering::LowerSIMD(GenTreeSIMD* simdNode) BlockRange().Remove(arg); } - // For SIMD12, even though there might be 12 bytes of constants, we need to store 16 bytes of data - // since we've bashed the node the TYP_SIMD16 and do a 16-byte indirection. - assert(varTypeIsSIMD(simdNode)); - const unsigned cnsSize = genTypeSize(simdNode); - assert(cnsSize <= sizeof(constArgValues)); + assert(sizeof(constArgValues) == 16); - const unsigned cnsAlign = - (comp->compCodeOpt() != Compiler::SMALL_CODE) ? cnsSize : emitter::dataSection::MIN_DATA_ALIGN; + unsigned cnsSize = sizeof(constArgValues); + unsigned cnsAlign = (comp->compCodeOpt() != Compiler::SMALL_CODE) ? cnsSize : 1; CORINFO_FIELD_HANDLE hnd = comp->GetEmitter()->emitBlkConst(constArgValues, cnsSize, cnsAlign, simdNode->GetSimdBaseType()); diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index 08eeb58143336..7e6acf6f03009 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -351,12 +351,11 @@ class Lowering final : public Phase GenTree* TryLowerAndOpToResetLowestSetBit(GenTreeOp* andNode); GenTree* TryLowerAndOpToExtractLowestSetBit(GenTreeOp* andNode); GenTree* TryLowerAndOpToAndNot(GenTreeOp* andNode); - GenTree* TryLowerXorOpToGetMaskUpToLowestSetBit(GenTreeOp* xorNode); void LowerBswapOp(GenTreeOp* node); #elif defined(TARGET_ARM64) bool IsValidConstForMovImm(GenTreeHWIntrinsic* node); void LowerHWIntrinsicFusedMultiplyAddScalar(GenTreeHWIntrinsic* node); - void LowerModPow2(GenTree* node); + GenTree* LowerModPow2(GenTree* node); GenTree* LowerAddForPossibleContainment(GenTreeOp* node); #endif // !TARGET_XARCH && !TARGET_ARM64 #endif // FEATURE_HW_INTRINSICS diff --git a/src/coreclr/jit/lowerarmarch.cpp b/src/coreclr/jit/lowerarmarch.cpp index ed77d2a954f17..5ee0c27767ee1 100644 --- a/src/coreclr/jit/lowerarmarch.cpp +++ b/src/coreclr/jit/lowerarmarch.cpp @@ -104,7 +104,6 @@ bool Lowering::IsContainableImmed(GenTree* parentNode, GenTree* childNode) const case GT_LE: case GT_GE: case GT_GT: - case GT_CMP: case GT_BOUNDS_CHECK: return emitter::emitIns_valid_imm_for_cmp(immVal, size); case GT_AND: @@ -575,44 +574,6 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT addr->SetContained(); } -//------------------------------------------------------------------------ -// LowerPutArgStk: Lower a GT_PUTARG_STK. -// -// Arguments: -// putArgStk - The node to lower -// -void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) -{ - GenTree* src = putArgStk->Data(); - - if (src->TypeIs(TYP_STRUCT)) - { - // STRUCT args (FIELD_LIST / OBJ / LCL_VAR / LCL_FLD) will always be contained. - MakeSrcContained(putArgStk, src); - - // TODO-ADDR: always perform this transformation in local morph and delete this code. - if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIsLocalAddr()) - { - GenTreeLclVarCommon* lclAddrNode = src->AsObj()->Addr()->AsLclVarCommon(); - unsigned lclNum = lclAddrNode->GetLclNum(); - unsigned lclOffs = lclAddrNode->GetLclOffs(); - ClassLayout* layout = src->AsObj()->GetLayout(); - - src->ChangeOper(GT_LCL_FLD); - src->AsLclFld()->SetLclNum(lclNum); - src->AsLclFld()->SetLclOffs(lclOffs); - src->AsLclFld()->SetLayout(layout); - - BlockRange().Remove(lclAddrNode); - } - else if (src->OperIs(GT_LCL_VAR)) - { - // TODO-1stClassStructs: support struct enregistration here by retyping "src" to its register type. - comp->lvaSetVarDoNotEnregister(src->AsLclVar()->GetLclNum() DEBUGARG(DoNotEnregisterReason::IsStructArg)); - } - } -} - //------------------------------------------------------------------------ // LowerCast: Lower GT_CAST(srcType, DstType) nodes. // @@ -700,26 +661,41 @@ void Lowering::LowerRotate(GenTree* tree) // Arguments: // tree - the node to lower // +// Return Value: +// A new tree node if it changed. +// // Notes: +// {expr} % {cns} +// Logically turns into: +// let a = {expr} +// if a > 0 then (a & ({cns} - 1)) else -(-a & ({cns} - 1)) +// which then turns into: +// and reg1, reg0, #({cns} - 1) +// negs reg0, reg0 +// and reg0, reg0, #({cns} - 1) +// csneg reg0, reg1, reg0, mi // TODO: We could do this optimization in morph but we do not have // a conditional select op in HIR. At some point, we may // introduce such an op. -void Lowering::LowerModPow2(GenTree* node) +GenTree* Lowering::LowerModPow2(GenTree* node) { assert(node->OperIs(GT_MOD)); - GenTreeOp* mod = node->AsOp(); - GenTree* dividend = mod->gtGetOp1(); - GenTree* divisor = mod->gtGetOp2(); - - JITDUMP("Lower: optimize X MOD POW2"); + GenTree* mod = node; + GenTree* dividend = mod->gtGetOp1(); + GenTree* divisor = mod->gtGetOp2(); assert(divisor->IsIntegralConstPow2()); const var_types type = mod->TypeGet(); assert((type == TYP_INT) || (type == TYP_LONG)); - ssize_t divisorCnsValue = static_cast(divisor->AsIntConCommon()->IntegralValue()); - ssize_t divisorCnsValueMinusOne = divisorCnsValue - 1; + LIR::Use use; + if (!BlockRange().TryGetUse(node, &use)) + { + return nullptr; + } + + ssize_t cnsValue = static_cast(divisor->AsIntConCommon()->IntegralValue()) - 1; BlockRange().Remove(divisor); @@ -731,64 +707,39 @@ void Lowering::LowerModPow2(GenTree* node) GenTree* dividend2 = comp->gtClone(dividend); BlockRange().InsertAfter(dividend, dividend2); - GenTreeIntCon* cns = comp->gtNewIconNode(divisorCnsValueMinusOne, type); + GenTreeIntCon* cns = comp->gtNewIconNode(cnsValue, type); BlockRange().InsertAfter(dividend2, cns); GenTree* const trueExpr = comp->gtNewOperNode(GT_AND, type, dividend, cns); BlockRange().InsertAfter(cns, trueExpr); LowerNode(trueExpr); - if (divisorCnsValue == 2) - { - // {expr} % 2 - // Logically turns into: - // let a = {expr} - // if a < 0 then -(a & 1) else (a & 1) - // which then turns into: - // and reg1, reg0, #1 - // cmp reg0, #0 - // cneg reg0, reg1, lt - - GenTreeIntCon* cnsZero = comp->gtNewIconNode(0, type); - BlockRange().InsertAfter(trueExpr, cnsZero); - - GenTree* const cmp = comp->gtNewOperNode(GT_CMP, type, dividend2, cnsZero); - cmp->gtFlags |= GTF_SET_FLAGS; - BlockRange().InsertAfter(cnsZero, cmp); - LowerNode(cmp); + GenTree* const neg = comp->gtNewOperNode(GT_NEG, type, dividend2); + neg->gtFlags |= GTF_SET_FLAGS; + BlockRange().InsertAfter(trueExpr, neg); - mod->ChangeOper(GT_CNEG_LT); - mod->gtOp1 = trueExpr; - } - else - { - // {expr} % {cns} - // Logically turns into: - // let a = {expr} - // if a > 0 then (a & ({cns} - 1)) else -(-a & ({cns} - 1)) - // which then turns into: - // and reg1, reg0, #({cns} - 1) - // negs reg0, reg0 - // and reg0, reg0, #({cns} - 1) - // csneg reg0, reg1, reg0, mi - - GenTree* const neg = comp->gtNewOperNode(GT_NEG, type, dividend2); - neg->gtFlags |= GTF_SET_FLAGS; - BlockRange().InsertAfter(trueExpr, neg); - - GenTreeIntCon* cns2 = comp->gtNewIconNode(divisorCnsValueMinusOne, type); - BlockRange().InsertAfter(neg, cns2); - - GenTree* const falseExpr = comp->gtNewOperNode(GT_AND, type, neg, cns2); - BlockRange().InsertAfter(cns2, falseExpr); - LowerNode(falseExpr); - - mod->ChangeOper(GT_CSNEG_MI); - mod->gtOp1 = trueExpr; - mod->gtOp2 = falseExpr; - } + GenTreeIntCon* cns2 = comp->gtNewIconNode(cnsValue, type); + BlockRange().InsertAfter(neg, cns2); + + GenTree* const falseExpr = comp->gtNewOperNode(GT_AND, type, neg, cns2); + BlockRange().InsertAfter(cns2, falseExpr); + LowerNode(falseExpr); + + GenTree* const cc = comp->gtNewOperNode(GT_CSNEG_MI, type, trueExpr, falseExpr); + cc->gtFlags |= GTF_USE_FLAGS; + + JITDUMP("Lower: optimize X MOD POW2"); + DISPNODE(mod); + JITDUMP("to:\n"); + DISPNODE(cc); + + BlockRange().InsertBefore(mod, cc); + ContainCheckNode(cc); + BlockRange().Remove(mod); + + use.ReplaceWith(cc); - ContainCheckNode(mod); + return cc->gtNext; } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/lowerloongarch64.cpp b/src/coreclr/jit/lowerloongarch64.cpp index 1de03b57e8e92..7a2cde0c4f5fb 100644 --- a/src/coreclr/jit/lowerloongarch64.cpp +++ b/src/coreclr/jit/lowerloongarch64.cpp @@ -416,30 +416,6 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT addr->SetContained(); } -//------------------------------------------------------------------------ -// LowerPutArgStk: Lower a GT_PUTARG_STK. -// -// Arguments: -// putArgStk - The node to lower -// -void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) -{ - GenTree* src = putArgStk->Data(); - - if (src->TypeIs(TYP_STRUCT)) - { - // STRUCT args (FIELD_LIST / OBJ) will always be contained. - MakeSrcContained(putArgStk, src); - - // Additionally, codegen supports containment of local addresses under OBJs. - if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIs(GT_LCL_VAR_ADDR)) - { - // TODO-LOONGARCH64-CQ: support containment of LCL_FLD_ADDR too. - MakeSrcContained(src, src->AsObj()->Addr()); - } - } -} - //------------------------------------------------------------------------ // LowerCast: Lower GT_CAST(srcType, DstType) nodes. // diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index e8be8b615c6d8..46990d9f6dbc6 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -174,35 +174,24 @@ GenTree* Lowering::LowerMul(GenTreeOp* mul) GenTree* Lowering::LowerBinaryArithmetic(GenTreeOp* binOp) { #ifdef FEATURE_HW_INTRINSICS - if (comp->opts.OptimizationEnabled() && varTypeIsIntegral(binOp)) + if (comp->opts.OptimizationEnabled() && binOp->OperIs(GT_AND) && varTypeIsIntegral(binOp)) { - if (binOp->OperIs(GT_AND)) + GenTree* replacementNode = TryLowerAndOpToAndNot(binOp); + if (replacementNode != nullptr) { - GenTree* replacementNode = TryLowerAndOpToAndNot(binOp); - if (replacementNode != nullptr) - { - return replacementNode->gtNext; - } - - replacementNode = TryLowerAndOpToResetLowestSetBit(binOp); - if (replacementNode != nullptr) - { - return replacementNode->gtNext; - } + return replacementNode->gtNext; + } - replacementNode = TryLowerAndOpToExtractLowestSetBit(binOp); - if (replacementNode != nullptr) - { - return replacementNode->gtNext; - } + replacementNode = TryLowerAndOpToResetLowestSetBit(binOp); + if (replacementNode != nullptr) + { + return replacementNode->gtNext; } - else if (binOp->OperIs(GT_XOR)) + + replacementNode = TryLowerAndOpToExtractLowestSetBit(binOp); + if (replacementNode != nullptr) { - GenTree* replacementNode = TryLowerXorOpToGetMaskUpToLowestSetBit(binOp); - if (replacementNode != nullptr) - { - return replacementNode->gtNext; - } + return replacementNode->gtNext; } } #endif @@ -466,11 +455,14 @@ void Lowering::ContainBlockStoreAddress(GenTreeBlk* blkNode, unsigned size, GenT // LowerPutArgStk: Lower a GT_PUTARG_STK. // // Arguments: -// putArgStk - The node of interest +// tree - The node of interest +// +// Return Value: +// None. // void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) { - GenTree* src = putArgStk->Data(); + GenTree* src = putArgStk->gtGetOp1(); bool srcIsLocal = src->OperIsLocalRead(); if (src->OperIs(GT_FIELD_LIST)) @@ -541,11 +533,9 @@ void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) #ifdef FEATURE_PUT_STRUCT_ARG_STK if (src->TypeIs(TYP_STRUCT)) { - assert(src->OperIs(GT_OBJ) || src->OperIsLocalRead()); - - ClassLayout* layout = src->GetLayout(comp); + ClassLayout* layout = src->AsObj()->GetLayout(); var_types regType = layout->GetRegisterType(); - srcIsLocal |= src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIsLocalAddr(); + srcIsLocal |= src->AsObj()->Addr()->OperIsLocalAddr(); if (regType == TYP_UNDEF) { @@ -555,24 +545,30 @@ void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) // The cpyXXXX code is rather complex and this could cause it to be more complex, but // it might be the right thing to do. - // If possible, widen the load, this results in more compact code. - unsigned loadSize = srcIsLocal ? roundUp(layout->GetSize(), TARGET_POINTER_SIZE) : layout->GetSize(); - putArgStk->SetArgLoadSize(loadSize); + unsigned size = putArgStk->GetStackByteSize(); + unsigned loadSize = layout->GetSize(); + + assert(loadSize <= size); // TODO-X86-CQ: The helper call either is not supported on x86 or required more work // (I don't know which). + if (!layout->HasGCPtr()) { #ifdef TARGET_X86 // Codegen for "Kind::Push" will always load bytes in TARGET_POINTER_SIZE - // chunks. As such, we'll only use this path for correctly-sized sources. - if ((loadSize < XMM_REGSIZE_BYTES) && ((loadSize % TARGET_POINTER_SIZE) == 0)) + // chunks. As such, the correctness of this code depends on the fact that + // morph will copy any "mis-sized" (too small) non-local OBJs into a temp, + // thus preventing any possible out-of-bounds memory reads. + assert(((layout->GetSize() % TARGET_POINTER_SIZE) == 0) || src->OperIsLocalRead() || + (src->OperIsIndir() && src->AsIndir()->Addr()->IsLocalAddrExpr())); + if (size < XMM_REGSIZE_BYTES) { putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::Push; } else #endif // TARGET_X86 - if (loadSize <= CPBLK_UNROLL_LIMIT) + if (size <= CPBLK_UNROLL_LIMIT) { putArgStk->gtPutArgStkKind = GenTreePutArgStk::Kind::Unroll; } @@ -593,25 +589,14 @@ void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) #endif // !TARGET_X86 } + // Always mark the OBJ and ADDR as contained trees by the putarg_stk. The codegen will deal with this tree. + MakeSrcContained(putArgStk, src); if (src->OperIs(GT_OBJ) && src->AsObj()->Addr()->OperIsLocalAddr()) { - // TODO-ADDR: always perform this transformation in local morph and delete this code. - GenTreeLclVarCommon* lclAddrNode = src->AsObj()->Addr()->AsLclVarCommon(); - BlockRange().Remove(lclAddrNode); - - src->ChangeOper(GT_LCL_FLD); - src->AsLclFld()->SetLclNum(lclAddrNode->GetLclNum()); - src->AsLclFld()->SetLclOffs(lclAddrNode->GetLclOffs()); - src->AsLclFld()->SetLayout(layout); + // If the source address is the address of a lclVar, make the source address contained to avoid + // unnecessary copies. + MakeSrcContained(putArgStk, src->AsObj()->Addr()); } - else if (src->OperIs(GT_LCL_VAR)) - { - comp->lvaSetVarDoNotEnregister(src->AsLclVar()->GetLclNum() - DEBUGARG(DoNotEnregisterReason::IsStructArg)); - } - - // Always mark the OBJ/LCL_VAR/LCL_FLD as contained trees. - MakeSrcContained(putArgStk, src); } else { @@ -619,17 +604,13 @@ void Lowering::LowerPutArgStk(GenTreePutArgStk* putArgStk) // so if possible, widen the load to avoid the sign/zero-extension. if (varTypeIsSmall(regType) && srcIsLocal) { - assert(genTypeSize(TYP_INT) <= putArgStk->GetStackByteSize()); + assert(putArgStk->GetStackByteSize() <= genTypeSize(TYP_INT)); regType = TYP_INT; } + src->SetOper(GT_IND); src->ChangeType(regType); - - if (src->OperIs(GT_OBJ)) - { - src->SetOper(GT_IND); - LowerIndir(src->AsIndir()); - } + LowerIndir(src->AsIndir()); } } @@ -4075,93 +4056,6 @@ GenTree* Lowering::TryLowerAndOpToAndNot(GenTreeOp* andNode) return andnNode; } -//---------------------------------------------------------------------------------------------- -// Lowering::TryLowerXorOpToGetMaskUpToLowestSetBit: Lowers a tree XOR(X, ADD(X, -1)) to -// HWIntrinsic::GetMaskUpToLowestSetBit -// -// Arguments: -// xorNode - GT_XOR node of integral type -// -// Return Value: -// Returns the replacement node if one is created else nullptr indicating no replacement -// -// Notes: -// Performs containment checks on the replacement node if one is created -GenTree* Lowering::TryLowerXorOpToGetMaskUpToLowestSetBit(GenTreeOp* xorNode) -{ - assert(xorNode->OperIs(GT_XOR) && varTypeIsIntegral(xorNode)); - - GenTree* op1 = xorNode->gtGetOp1(); - if (!op1->OperIs(GT_LCL_VAR) || comp->lvaGetDesc(op1->AsLclVar())->IsAddressExposed()) - { - return nullptr; - } - - GenTree* op2 = xorNode->gtGetOp2(); - if (!op2->OperIs(GT_ADD)) - { - return nullptr; - } - - GenTree* addOp2 = op2->gtGetOp2(); - if (!addOp2->IsIntegralConst(-1)) - { - return nullptr; - } - - GenTree* addOp1 = op2->gtGetOp1(); - if (!addOp1->OperIs(GT_LCL_VAR) || (addOp1->AsLclVar()->GetLclNum() != op1->AsLclVar()->GetLclNum())) - { - return nullptr; - } - - // Subsequent nodes may rely on CPU flags set by these nodes in which case we cannot remove them - if (((addOp2->gtFlags & GTF_SET_FLAGS) != 0) || ((op2->gtFlags & GTF_SET_FLAGS) != 0) || - ((xorNode->gtFlags & GTF_SET_FLAGS) != 0)) - { - return nullptr; - } - - NamedIntrinsic intrinsic; - if (xorNode->TypeIs(TYP_LONG) && comp->compOpportunisticallyDependsOn(InstructionSet_BMI1_X64)) - { - intrinsic = NamedIntrinsic::NI_BMI1_X64_GetMaskUpToLowestSetBit; - } - else if (comp->compOpportunisticallyDependsOn(InstructionSet_BMI1)) - { - intrinsic = NamedIntrinsic::NI_BMI1_GetMaskUpToLowestSetBit; - } - else - { - return nullptr; - } - - LIR::Use use; - if (!BlockRange().TryGetUse(xorNode, &use)) - { - return nullptr; - } - - GenTreeHWIntrinsic* blsmskNode = comp->gtNewScalarHWIntrinsicNode(xorNode->TypeGet(), op1, intrinsic); - - JITDUMP("Lower: optimize XOR(X, ADD(X, -1)))\n"); - DISPNODE(xorNode); - JITDUMP("to:\n"); - DISPNODE(blsmskNode); - - use.ReplaceWith(blsmskNode); - - BlockRange().InsertBefore(xorNode, blsmskNode); - BlockRange().Remove(xorNode); - BlockRange().Remove(op2); - BlockRange().Remove(addOp1); - BlockRange().Remove(addOp2); - - ContainCheckHWIntrinsic(blsmskNode); - - return blsmskNode; -} - //---------------------------------------------------------------------------------------------- // Lowering::LowerBswapOp: Tries to contain GT_BSWAP node when possible // @@ -4719,6 +4613,22 @@ void Lowering::ContainCheckCallOperands(GenTreeCall* call) MakeSrcContained(call, ctrlExpr); } } + + for (CallArg& arg : call->gtArgs.EarlyArgs()) + { + if (arg.GetEarlyNode()->OperIs(GT_PUTARG_STK)) + { + LowerPutArgStk(arg.GetEarlyNode()->AsPutArgStk()); + } + } + + for (CallArg& arg : call->gtArgs.LateArgs()) + { + if (arg.GetLateNode()->OperIs(GT_PUTARG_STK)) + { + LowerPutArgStk(arg.GetLateNode()->AsPutArgStk()); + } + } } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/lsraarmarch.cpp b/src/coreclr/jit/lsraarmarch.cpp index 3d1cf8540a142..4a9eefef350c5 100644 --- a/src/coreclr/jit/lsraarmarch.cpp +++ b/src/coreclr/jit/lsraarmarch.cpp @@ -403,19 +403,20 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) { assert(argNode->gtOper == GT_PUTARG_STK); - GenTree* src = argNode->Data(); - int srcCount = 0; + GenTree* putArgChild = argNode->gtGetOp1(); + + int srcCount = 0; - // Do we have a TYP_STRUCT argument, if so it must be a multireg pass-by-value struct - if (src->TypeIs(TYP_STRUCT)) + // Do we have a TYP_STRUCT argument (or a GT_FIELD_LIST), if so it must be a multireg pass-by-value struct + if (putArgChild->TypeIs(TYP_STRUCT) || putArgChild->OperIs(GT_FIELD_LIST)) { // We will use store instructions that each write a register sized value - if (src->OperIs(GT_FIELD_LIST)) + if (putArgChild->OperIs(GT_FIELD_LIST)) { - assert(src->isContained()); + assert(putArgChild->isContained()); // We consume all of the items in the GT_FIELD_LIST - for (GenTreeFieldList::Use& use : src->AsFieldList()->Uses()) + for (GenTreeFieldList::Use& use : putArgChild->AsFieldList()->Uses()) { BuildUse(use.GetNode()); srcCount++; @@ -442,25 +443,36 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* argNode) buildInternalIntRegisterDefForNode(argNode); #endif // TARGET_ARM64 - assert(src->isContained()); - - if (src->OperIs(GT_OBJ)) + if (putArgChild->OperGet() == GT_OBJ) { - // Build uses for the address to load from. - // - srcCount = BuildOperandUses(src->AsObj()->Addr()); + assert(putArgChild->isContained()); + GenTree* objChild = putArgChild->gtGetOp1(); + if (objChild->OperGet() == GT_LCL_VAR_ADDR) + { + // We will generate all of the code for the GT_PUTARG_STK, the GT_OBJ and the GT_LCL_VAR_ADDR + // as one contained operation, and there are no source registers. + // + assert(objChild->isContained()); + } + else + { + // We will generate all of the code for the GT_PUTARG_STK and its child node + // as one contained operation + // + srcCount = BuildOperandUses(objChild); + } } else { // No source registers. - assert(src->OperIs(GT_LCL_VAR, GT_LCL_FLD)); + putArgChild->OperIs(GT_LCL_VAR); } } } else { - assert(!src->isContained()); - srcCount = BuildOperandUses(src); + assert(!putArgChild->isContained()); + srcCount = BuildOperandUses(putArgChild); #if defined(FEATURE_SIMD) if (compMacOsArm64Abi() && argNode->GetStackByteSize() == 12) { @@ -808,6 +820,13 @@ int LinearScan::BuildCast(GenTreeCast* cast) buildInternalFloatRegisterDefForNode(cast, RBM_ALLFLOAT); setInternalRegsDelayFree = true; } +#else + // Overflow checking cast from TYP_LONG to TYP_INT requires a temporary register to + // store the min and max immediate values that cannot be encoded in the CMP instruction. + if (cast->gtOverflow() && varTypeIsLong(srcType) && !cast->IsUnsigned() && (castType == TYP_INT)) + { + buildInternalIntRegisterDefForNode(cast); + } #endif int srcCount = BuildOperandUses(src); diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 6ed5665febdc5..5386ed5769558 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1561,31 +1561,21 @@ int LinearScan::BuildPutArgStk(GenTreePutArgStk* putArgStk) return BuildOperandUses(src); } - unsigned loadSize = putArgStk->GetArgLoadSize(); + ssize_t size = putArgStk->GetStackByteSize(); switch (putArgStk->gtPutArgStkKind) { case GenTreePutArgStk::Kind::Unroll: // If we have a remainder smaller than XMM_REGSIZE_BYTES, we need an integer temp reg. - if ((loadSize % XMM_REGSIZE_BYTES) != 0) + if ((size % XMM_REGSIZE_BYTES) != 0) { regMaskTP regMask = allRegs(TYP_INT); -#ifdef TARGET_X86 - // Storing at byte granularity requires a byteable register. - if ((loadSize & 1) != 0) - { - regMask &= allByteRegs(); - } -#endif // TARGET_X86 buildInternalIntRegisterDefForNode(putArgStk, regMask); } -#ifdef TARGET_X86 - if (loadSize >= 8) -#else - if (loadSize >= XMM_REGSIZE_BYTES) -#endif + if (size >= XMM_REGSIZE_BYTES) { - // See "genStructPutArgUnroll" -- we will use this XMM register for wide stores. + // If we have a buffer larger than or equal to XMM_REGSIZE_BYTES, reserve + // an XMM register to use it for a series of 16-byte loads and stores. buildInternalFloatRegisterDefForNode(putArgStk, internalFloatRegCandidates()); SetContainsAVXFlags(); } @@ -2491,9 +2481,9 @@ int LinearScan::BuildCast(GenTreeCast* cast) assert(!varTypeIsLong(srcType) || (src->OperIs(GT_LONG) && src->isContained())); #else - // Overflow checking cast from TYP_(U)LONG to TYP_(U)INT requires a temporary + // Overflow checking cast from TYP_(U)LONG to TYP_UINT requires a temporary // register to extract the upper 32 bits of the 64 bit source register. - if (cast->gtOverflow() && varTypeIsLong(srcType) && varTypeIsInt(castType)) + if (cast->gtOverflow() && varTypeIsLong(srcType) && (castType == TYP_UINT)) { // Here we don't need internal register to be different from targetReg, // rather require it to be different from operand's reg. diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index 22fe9739444b4..ec5d602d5eb64 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -179,7 +179,16 @@ GenTree* Compiler::fgMorphIntoHelperCall(GenTree* tree, int helper, bool morphAr // GenTree* Compiler::fgMorphExpandCast(GenTreeCast* tree) { - GenTree* oper = tree->CastOp(); + GenTree* oper = tree->CastOp(); + + if (fgGlobalMorph && (oper->gtOper == GT_ADDR)) + { + // Make sure we've checked if 'oper' is an address of an implicit-byref parameter. + // If it is, fgMorphImplicitByRefArgs will change its type, and we want the cast + // morphing code to see that type. + fgMorphImplicitByRefArgs(oper); + } + var_types srcType = genActualType(oper); var_types dstType = tree->CastToType(); unsigned dstSize = genTypeSize(dstType); @@ -735,12 +744,6 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) unsigned argCount = CountArgs(); - // Previous argument with GTF_EXCEPT - GenTree* prevExceptionTree = nullptr; - // Exceptions previous tree with GTF_EXCEPT may throw (computed lazily, may - // be empty) - ExceptionSetFlags prevExceptionFlags = ExceptionSetFlags::None; - for (CallArg& arg : Args()) { GenTree* argx = arg.GetEarlyNode(); @@ -752,14 +755,15 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) continue; } - bool canEvalToTemp = true; if (arg.AbiInfo.GetRegNum() == REG_STK) { assert(m_hasStackArgs); #if !FEATURE_FIXED_OUT_ARGS - // Non-register arguments are evaluated and pushed in order; they - // should never go in the late arg list. - canEvalToTemp = false; + // On x86 we use push instructions to pass arguments: + // The non-register arguments are evaluated and pushed in order + // and they are never evaluated into temps + // + continue; #endif } #if FEATURE_ARG_SPLIT @@ -792,20 +796,17 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) if (argx->gtFlags & GTF_ASG) { - // If this is not the only argument, or it's a copyblk, or it - // already evaluates the expression to a tmp then we need a temp in - // the late arg list. - // In the latter case this might not even be a value; - // fgMakeOutgoingStructArgCopy will leave the copying nodes here - // for FEATURE_FIXED_OUT_ARGS. - if (canEvalToTemp && ((argCount > 1) || argx->OperIsCopyBlkOp() || (FEATURE_FIXED_OUT_ARGS && arg.m_isTmp))) + // If this is not the only argument, or it's a copyblk, or it already evaluates the expression to + // a tmp, then we need a temp in the late arg list. + if ((argCount > 1) || argx->OperIsCopyBlkOp() +#ifdef FEATURE_FIXED_OUT_ARGS + || arg.m_isTmp // Protect this by "FEATURE_FIXED_OUT_ARGS" to preserve the property + // that we only have late non-register args when that feature is on. +#endif + ) { SetNeedsTemp(&arg); } - else - { - assert(argx->IsValue()); - } // For all previous arguments, unless they are a simple constant // we require that they be evaluated into temps @@ -816,16 +817,6 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) break; } -#if !FEATURE_FIXED_OUT_ARGS - if (prevArg.AbiInfo.GetRegNum() == REG_STK) - { - // All stack args are already evaluated and placed in order - // in this case; we only need to check this for register - // args. - break; - } -#endif - if ((prevArg.GetEarlyNode() != nullptr) && !prevArg.GetEarlyNode()->IsInvariant()) { SetNeedsTemp(&prevArg); @@ -834,8 +825,6 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) } bool treatLikeCall = ((argx->gtFlags & GTF_CALL) != 0); - - ExceptionSetFlags exceptionFlags = ExceptionSetFlags::None; #if FEATURE_FIXED_OUT_ARGS // Like calls, if this argument has a tree that will do an inline throw, // a call to a jit helper, then we need to treat it like a call (but only @@ -844,49 +833,43 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) // conservative, but I want to avoid as much special-case debug-only code // as possible, so leveraging the GTF_CALL flag is the easiest. // - if (!treatLikeCall && (argx->gtFlags & GTF_EXCEPT) && (argCount > 1) && comp->opts.compDbgCode) + if (!treatLikeCall && (argx->gtFlags & GTF_EXCEPT) && (argCount > 1) && comp->opts.compDbgCode && + (comp->fgWalkTreePre(&argx, Compiler::fgChkThrowCB) == Compiler::WALK_ABORT)) { - exceptionFlags = comp->gtCollectExceptions(argx); - if ((exceptionFlags & (ExceptionSetFlags::IndexOutOfRangeException | - ExceptionSetFlags::OverflowException)) != ExceptionSetFlags::None) + for (CallArg& otherArg : Args()) { - for (CallArg& otherArg : Args()) + if (&otherArg == &arg) { - if (&otherArg == &arg) - { - continue; - } + continue; + } - if (otherArg.AbiInfo.GetRegNum() == REG_STK) - { - treatLikeCall = true; - break; - } + if (otherArg.AbiInfo.GetRegNum() == REG_STK) + { + treatLikeCall = true; + break; } } } #endif // FEATURE_FIXED_OUT_ARGS - // If it contains a call (GTF_CALL) then itself and everything before the call - // with a GLOB_EFFECT must eval to temp (this is because everything with SIDE_EFFECT - // has to be kept in the right order since we will move the call to the first position) + /* If it contains a call (GTF_CALL) then itself and everything before the call + with a GLOB_EFFECT must eval to temp (this is because everything with SIDE_EFFECT + has to be kept in the right order since we will move the call to the first position) - // For calls we don't have to be quite as conservative as we are with an assignment - // since the call won't be modifying any non-address taken LclVars. + For calls we don't have to be quite as conservative as we are with an assignment + since the call won't be modifying any non-address taken LclVars. + */ if (treatLikeCall) { - if (canEvalToTemp) + if (argCount > 1) // If this is not the only argument { - if (argCount > 1) // If this is not the only argument - { - SetNeedsTemp(&arg); - } - else if (varTypeIsFloating(argx->TypeGet()) && (argx->OperGet() == GT_CALL)) - { - // Spill all arguments that are floating point calls - SetNeedsTemp(&arg); - } + SetNeedsTemp(&arg); + } + else if (varTypeIsFloating(argx->TypeGet()) && (argx->OperGet() == GT_CALL)) + { + // Spill all arguments that are floating point calls + SetNeedsTemp(&arg); } // All previous arguments may need to be evaluated into temps @@ -897,15 +880,6 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) break; } -#if !FEATURE_FIXED_OUT_ARGS - if (prevArg.AbiInfo.GetRegNum() == REG_STK) - { - // All stack args are already evaluated and placed in order - // in this case. - break; - } -#endif - // For all previous arguments, if they have any GTF_ALL_EFFECT // we require that they be evaluated into a temp if ((prevArg.GetEarlyNode() != nullptr) && ((prevArg.GetEarlyNode()->gtFlags & GTF_ALL_EFFECT) != 0)) @@ -914,7 +888,8 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) } #if FEATURE_FIXED_OUT_ARGS // Or, if they are stored into the FIXED_OUT_ARG area - // we require that they be moved to the late list + // we require that they be moved to the gtCallLateArgs + // and replaced with a placeholder node else if (prevArg.AbiInfo.GetRegNum() == REG_STK) { prevArg.m_needPlace = true; @@ -928,64 +903,6 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) #endif } } - else if ((argx->gtFlags & GTF_EXCEPT) != 0) - { - // If a previous arg may throw a different exception than this arg - // then we evaluate all previous arguments with GTF_EXCEPT to temps - // to avoid reordering them in our sort later. - if (prevExceptionTree != nullptr) - { - if (prevExceptionFlags == ExceptionSetFlags::None) - { - prevExceptionFlags = comp->gtCollectExceptions(prevExceptionTree); - } - - if (exceptionFlags == ExceptionSetFlags::None) - { - exceptionFlags = comp->gtCollectExceptions(argx); - } - - bool exactlyOne = isPow2(static_cast(exceptionFlags)); - bool throwsSameAsPrev = exactlyOne && (exceptionFlags == prevExceptionFlags); - if (!throwsSameAsPrev) - { - JITDUMP("Exception set for arg [%06u] interferes with previous tree [%06u]; must evaluate previous " - "trees with exceptions to temps\n", - Compiler::dspTreeID(argx), Compiler::dspTreeID(prevExceptionTree)); - - for (CallArg& prevArg : Args()) - { - if (&prevArg == &arg) - { - break; - } - -#if !FEATURE_FIXED_OUT_ARGS - if (prevArg.AbiInfo.GetRegNum() == REG_STK) - { - // All stack args are already evaluated and placed in order - // in this case. - break; - } -#endif - // Invariant here is that all nodes that were not - // already evaluated into temps and that throw can only - // be throwing the same single exception as the - // previous tree, so all of them interfere in the same - // way with the current arg and must be evaluated - // early. - if ((prevArg.GetEarlyNode() != nullptr) && - ((prevArg.GetEarlyNode()->gtFlags & GTF_EXCEPT) != 0)) - { - SetNeedsTemp(&prevArg); - } - } - } - } - - prevExceptionTree = argx; - prevExceptionFlags = exceptionFlags; - } #if FEATURE_MULTIREG_ARGS // For RyuJIT backend we will expand a Multireg arg into a GT_FIELD_LIST @@ -1016,10 +933,25 @@ void CallArgs::ArgsComplete(Compiler* comp, GenTreeCall* call) SetNeedsTemp(&arg); } #if defined(FEATURE_SIMD) && defined(TARGET_ARM64) - else if (isMultiRegArg && varTypeIsSIMD(argx) && (argx->OperIsSimdOrHWintrinsic() || argx->IsCnsVec())) + else if (isMultiRegArg && varTypeIsSIMD(argx->TypeGet())) { - // Multi-reg morphing does not handle these SIMD nodes. - SetNeedsTemp(&arg); + GenTree* nodeToCheck = argx; + + if (nodeToCheck->OperIs(GT_OBJ)) + { + nodeToCheck = nodeToCheck->AsObj()->gtOp1; + + if (nodeToCheck->OperIs(GT_ADDR)) + { + nodeToCheck = nodeToCheck->AsOp()->gtOp1; + } + } + + // SIMD types do not need the optimization below due to their sizes + if (nodeToCheck->OperIsSimdOrHWintrinsic() || nodeToCheck->IsCnsVec()) + { + SetNeedsTemp(&arg); + } } #endif #ifndef TARGET_ARM @@ -1190,7 +1122,12 @@ void CallArgs::SortArgs(Compiler* comp, GenTreeCall* call, CallArg** sortedArgs) { assert(m_argsComplete); - JITDUMP("\nSorting the arguments:\n"); +#ifdef DEBUG + if (comp->verbose) + { + printf("\nSorting the arguments:\n"); + } +#endif // Shuffle the arguments around before we build the late args list. The // idea is to move all "simple" arguments like constants and local vars to @@ -1491,6 +1428,7 @@ GenTree* CallArgs::MakeTmpArgNode(Compiler* comp, CallArg* arg) if (varTypeIsStruct(type)) { + #if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_ARM) || defined(TARGET_LOONGARCH64) // Can this type be passed as a primitive type? @@ -1562,8 +1500,21 @@ GenTree* CallArgs::MakeTmpArgNode(Compiler* comp, CallArg* arg) #endif // !(TARGET_ARM64 || TARGET_LOONGARCH64) #endif // FEATURE_MULTIREG_ARGS } -#endif // (TARGET_AMD64 or TARGET_ARM64 or TARGET_ARM or TARGET_LOONGARCH64) - } // (varTypeIsStruct(type)) + +#else // not (TARGET_AMD64 or TARGET_ARM64 or TARGET_ARM or TARGET_LOONGARCH64) + + // other targets, we pass the struct by value + assert(varTypeIsStruct(type)); + + addrNode = comp->gtNewOperNode(GT_ADDR, TYP_BYREF, argNode); + + // Get a new Obj node temp to use it as a call argument. + // gtNewObjNode will set the GTF_EXCEPT flag if this is not a local stack object. + argNode = comp->gtNewObjNode(comp->lvaGetStruct(tmpVarNum), addrNode); + +#endif // not (TARGET_AMD64 or TARGET_ARM64 or TARGET_ARM or TARGET_LOONGARCH64) + + } // (varTypeIsStruct(type)) if (addrNode != nullptr) { @@ -1844,7 +1795,7 @@ void CallArgs::EvalArgsToTemps(Compiler* comp, GenTreeCall* call) #ifdef DEBUG if (comp->verbose) { - printf("\nRegister placement order: "); + printf("\nShuffled argument table: "); for (CallArg& arg : LateArgs()) { if (arg.AbiInfo.GetRegNum() != REG_STK) @@ -2156,21 +2107,21 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call size_t addrValue = (size_t)call->gtEntryPoint.addr; GenTree* indirectCellAddress = comp->gtNewIconHandleNode(addrValue, GTF_ICON_FTN_ADDR); - INDEBUG(indirectCellAddress->AsIntCon()->gtTargetHandle = (size_t)call->gtCallMethHnd); - -#ifdef TARGET_ARM - // TODO-ARM: We currently do not properly kill this register in LSRA - // (see getKillSetForCall which does so only for VSD calls). - // We should be able to remove these two workarounds once we do so, - // however when this was tried there were significant regressions. +#ifdef DEBUG + indirectCellAddress->AsIntCon()->gtTargetHandle = (size_t)call->gtCallMethHnd; +#endif indirectCellAddress->SetRegNum(REG_R2R_INDIRECT_PARAM); +#ifdef TARGET_ARM + // Issue #xxxx : Don't attempt to CSE this constant on ARM32 + // + // This constant has specific register requirements, and LSRA doesn't currently correctly + // handle them when the value is in a CSE'd local. indirectCellAddress->SetDoNotCSE(); -#endif +#endif // TARGET_ARM // Push the stub address onto the list of arguments. - NewCallArg indirCellAddrArg = - NewCallArg::Primitive(indirectCellAddress).WellKnown(WellKnownArg::R2RIndirectionCell); - InsertAfterThisOrFirst(comp, indirCellAddrArg); + InsertAfterThisOrFirst(comp, + NewCallArg::Primitive(indirectCellAddress).WellKnown(WellKnownArg::R2RIndirectionCell)); } #endif @@ -2284,12 +2235,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call argx->gtType = TYP_I_IMPL; } - // Note we must use the signature types for making ABI decisions. This is especially important for structs, - // where the "argx" node can legally have a type that is not ABI-compatible with the one in the signature. - const var_types argSigType = arg.GetSignatureType(); - const CORINFO_CLASS_HANDLE argSigClass = arg.GetSignatureClassHandle(); - - // Setup any HFA information about the argument. + // Setup any HFA information about 'argx' bool isHfaArg = false; var_types hfaType = TYP_UNDEF; unsigned hfaSlots = 0; @@ -2301,7 +2247,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call if (GlobalJitOptions::compFeatureHfa) { - hfaType = comp->GetHfaType(argSigClass); + hfaType = comp->GetHfaType(argx); isHfaArg = varTypeIsValidHfaType(hfaType); #if defined(TARGET_ARM64) @@ -2314,7 +2260,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call if (isHfaArg) { - hfaSlots = comp->GetHfaCount(argSigClass); + hfaSlots = comp->GetHfaCount(argx); // If we have a HFA struct it's possible we transition from a method that originally // only had integer types to now start having FP types. We have to communicate this @@ -2328,19 +2274,11 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call const bool isFloatHfa = (hfaType == TYP_FLOAT); #ifdef TARGET_ARM - passUsingFloatRegs = - !callIsVararg && (isHfaArg || varTypeUsesFloatReg(argSigType)) && !comp->opts.compUseSoftFP; + passUsingFloatRegs = !callIsVararg && (isHfaArg || varTypeUsesFloatReg(argx)) && !comp->opts.compUseSoftFP; bool passUsingIntRegs = passUsingFloatRegs ? false : (intArgRegNum < MAX_REG_ARG); - // TODO-Cleanup: use "eeGetArgSizeAlignment" here. See also: https://github.com/dotnet/runtime/issues/46026. - if (varTypeIsStruct(argSigType)) - { - argAlignBytes = comp->info.compCompHnd->getClassAlignmentRequirement(argSigClass); - } - else - { - argAlignBytes = genTypeSize(argSigType); - } + // We don't use the "size" return value from InferOpSizeAlign(). + comp->codeGen->InferOpSizeAlign(argx, &argAlignBytes); argAlignBytes = roundUp(argAlignBytes, TARGET_POINTER_SIZE); @@ -2367,11 +2305,11 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call #elif defined(TARGET_ARM64) assert(!callIsVararg || !isHfaArg); - passUsingFloatRegs = !callIsVararg && (isHfaArg || varTypeUsesFloatReg(argSigType)); + passUsingFloatRegs = !callIsVararg && (isHfaArg || varTypeUsesFloatReg(argx)); #elif defined(TARGET_AMD64) - passUsingFloatRegs = varTypeIsFloating(argSigType); + passUsingFloatRegs = varTypeIsFloating(argx); #elif defined(TARGET_X86) @@ -2380,7 +2318,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call #elif defined(TARGET_LOONGARCH64) assert(!callIsVararg && !isHfaArg); - passUsingFloatRegs = varTypeUsesFloatReg(argSigType); + passUsingFloatRegs = varTypeUsesFloatReg(argx); DWORD floatFieldFlags = STRUCT_NO_FLOAT_FIELD; #else @@ -2389,44 +2327,73 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call bool isBackFilled = false; unsigned nextFltArgRegNum = fltArgRegNum; // This is the next floating-point argument register number to use - bool isStructArg = varTypeIsStruct(argSigType); var_types structBaseType = TYP_STRUCT; unsigned structSize = 0; bool passStructByRef = false; + bool isStructArg; + GenTree* actualArg = argx->gtEffectiveVal(true /* Commas only */); + // // Figure out the size of the argument. This is either in number of registers, or number of // TARGET_POINTER_SIZE stack slots, or the sum of these if the argument is split between the registers and // the stack. // - + isStructArg = varTypeIsStruct(argx); + // Note that we internally in the JIT can change some struct args to + // primitive args (e.g. OBJ(x) -> IND(x)). Similarly, + // the ABI type can also change from struct to primitive (e.g. a 8-byte + // struct passed in a register). So isStructArg may be false even if + // the signature type was (or is) a struct, however only in cases where + // it does not matter. + CORINFO_CLASS_HANDLE objClass = NO_CLASS_HANDLE; if (isStructArg) { - GenTree* actualArg = argx->gtEffectiveVal(true /* Commas only */); - - // Here we look at "actualArg" to avoid calling "getClassSize". - structSize = actualArg->TypeIs(TYP_STRUCT) ? actualArg->GetLayout(comp)->GetSize() : genTypeSize(actualArg); - - assert(structSize == comp->info.compCompHnd->getClassSize(argSigClass)); + objClass = comp->gtGetStructHandle(argx); + if (argx->TypeGet() == TYP_STRUCT) + { + // For TYP_STRUCT arguments we must have an OBJ, LCL_VAR or MKREFANY + switch (actualArg->OperGet()) + { + case GT_OBJ: + structSize = actualArg->AsObj()->GetLayout()->GetSize(); + assert(structSize == comp->info.compCompHnd->getClassSize(objClass)); + break; + case GT_LCL_VAR: + structSize = comp->lvaGetDesc(actualArg->AsLclVarCommon())->lvExactSize; + break; + case GT_MKREFANY: + structSize = comp->info.compCompHnd->getClassSize(objClass); + break; + default: + BADCODE("illegal argument tree: cannot determine size for ABI handling"); + break; + } + } + else + { + structSize = genTypeSize(argx); + assert(structSize == comp->info.compCompHnd->getClassSize(objClass)); + } } #if defined(TARGET_AMD64) #ifdef UNIX_AMD64_ABI if (!isStructArg) { size = 1; // On AMD64, all primitives fit in a single (64-bit) 'slot' - byteSize = genTypeSize(argSigType); + byteSize = genTypeSize(arg.GetSignatureType()); } else { size = (unsigned)(roundUp(structSize, TARGET_POINTER_SIZE)) / TARGET_POINTER_SIZE; byteSize = structSize; - comp->eeGetSystemVAmd64PassStructInRegisterDescriptor(argSigClass, &structDesc); + comp->eeGetSystemVAmd64PassStructInRegisterDescriptor(objClass, &structDesc); } #else // !UNIX_AMD64_ABI size = 1; // On AMD64 Windows, all args fit in a single (64-bit) 'slot' if (!isStructArg) { - byteSize = genTypeSize(argSigType); + byteSize = genTypeSize(arg.GetSignatureType()); } #endif // UNIX_AMD64_ABI @@ -2437,8 +2404,9 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call { // HFA structs are passed by value in multiple registers. // The "size" in registers may differ the size in pointer-sized units. - size = hfaSlots; - byteSize = structSize; + CORINFO_CLASS_HANDLE structHnd = comp->gtGetStructHandle(argx); + size = comp->GetHfaCount(structHnd); + byteSize = comp->info.compCompHnd->getClassSize(structHnd); } else { @@ -2454,13 +2422,13 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call size = 1; } } - // Note that there are some additional rules for multireg structs on ARM64. + // Note that there are some additional rules for multireg structs. // (i.e they cannot be split between registers and the stack) } else { size = 1; // Otherwise, all primitive types fit in a single (64-bit) 'slot' - byteSize = genTypeSize(argSigType); + byteSize = genTypeSize(arg.GetSignatureType()); } #elif defined(TARGET_ARM) || defined(TARGET_X86) if (isStructArg) @@ -2472,8 +2440,8 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call { // The typical case. // Long/double type argument(s) will be modified as needed in Lowering. - size = genTypeStSz(argSigType); - byteSize = genTypeSize(argSigType); + size = genTypeStSz(argx->gtType); + byteSize = genTypeSize(arg.GetSignatureType()); } #else #error Unsupported or unset target architecture @@ -2485,14 +2453,14 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call assert(structSize != 0); Compiler::structPassingKind howToPassStruct; - structBaseType = comp->getArgTypeForStruct(argSigClass, &howToPassStruct, callIsVararg, structSize); + structBaseType = comp->getArgTypeForStruct(objClass, &howToPassStruct, callIsVararg, structSize); passStructByRef = (howToPassStruct == Compiler::SPK_ByReference); #if defined(TARGET_LOONGARCH64) if (!passStructByRef) { assert((howToPassStruct == Compiler::SPK_ByValue) || (howToPassStruct == Compiler::SPK_PrimitiveType)); - floatFieldFlags = comp->info.compCompHnd->getLoongArch64PassStructInRegisterFlags(argSigClass); + floatFieldFlags = comp->info.compCompHnd->getLoongArch64PassStructInRegisterFlags(objClass); passUsingFloatRegs = (floatFieldFlags & STRUCT_HAS_FLOAT_FIELDS_MASK) ? true : false; comp->compFloatingPointUsed |= passUsingFloatRegs; @@ -2503,7 +2471,8 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call // for "struct { float, float }", and retyping to a primitive here will cause the // multi-reg morphing to not kick in (the struct in question needs to be passed in // two FP registers). Here is just keep "structBaseType" as "TYP_STRUCT". - // TODO-LoongArch64: fix "getPrimitiveTypeForStruct". + // TODO-LoongArch64: fix "getPrimitiveTypeForStruct" or use the ABI information in + // the arg entry instead of calling it here. structBaseType = TYP_STRUCT; } @@ -2562,7 +2531,7 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call // Arm64 Apple has a special ABI for passing small size arguments on stack, // bytes are aligned to 1-byte, shorts to 2-byte, int/float to 4-byte, etc. // It means passing 8 1-byte arguments on stack can take as small as 8 bytes. - argAlignBytes = comp->eeGetArgSizeAlignment(argSigType, isFloatHfa); + argAlignBytes = comp->eeGetArgSizeAlignment(arg.GetSignatureType(), isFloatHfa); } #ifdef TARGET_LOONGARCH64 @@ -2574,11 +2543,11 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call bool isRegArg = false; regNumber nonStdRegNum = REG_NA; - if (isRegParamType(genActualType(argSigType)) + if (isRegParamType(genActualType(argx->TypeGet())) #ifdef UNIX_AMD64_ABI && (!isStructArg || structDesc.passedInRegisters) #elif defined(TARGET_X86) - || (isStructArg && comp->isTrivialPointerSizedStruct(argSigClass)) + || (isStructArg && comp->isTrivialPointerSizedStruct(objClass)) #endif ) { @@ -3034,9 +3003,12 @@ void CallArgs::AddFinalArgsAndDetermineABIInfo(Compiler* comp, GenTreeCall* call #endif } - if (isHfaArg) + if (GlobalJitOptions::compFeatureHfa) { - arg.AbiInfo.SetHfaType(hfaType, hfaSlots); + if (isHfaArg) + { + arg.AbiInfo.SetHfaType(hfaType, hfaSlots); + } } arg.AbiInfo.SetMultiRegNums(); @@ -3227,8 +3199,15 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) unsigned originalSize; if (argObj->TypeGet() == TYP_STRUCT) { - assert(argObj->OperIs(GT_OBJ, GT_LCL_VAR, GT_LCL_FLD)); - originalSize = argObj->GetLayout(this)->GetSize(); + if (argObj->OperIs(GT_OBJ)) + { + originalSize = argObj->AsObj()->Size(); + } + else + { + // Must be LCL_VAR: we have a BADCODE assert for this in AddFinalArgsAndDetermineABIInfo. + originalSize = lvaGetDesc(argObj->AsLclVar())->lvExactSize; + } } else { @@ -3429,28 +3408,13 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) makeOutArgCopy = true; } } - else if (genTypeSize(varDsc) != genTypeSize(structBaseType)) + else if (genTypeSize(varDsc->TypeGet()) != genTypeSize(structBaseType)) { // Not a promoted struct, so just swizzle the type by using GT_LCL_FLD lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::SwizzleArg)); argObj->ChangeOper(GT_LCL_FLD); argObj->gtType = structBaseType; } - else if (varTypeUsesFloatReg(varDsc) != varTypeUsesFloatReg(structBaseType)) - { - // Here we can see int <-> float, long <-> double, long <-> simd8 mismatches, due - // to the "OBJ(ADDR(LCL))" => "LCL" folding above. The latter case is handled in - // lowering, others we will handle here via swizzling. - CLANG_FORMAT_COMMENT_ANCHOR; -#ifdef TARGET_AMD64 - if (varDsc->TypeGet() != TYP_SIMD8) -#endif // TARGET_AMD64 - { - lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::SwizzleArg)); - argObj->ChangeOper(GT_LCL_FLD); - argObj->gtType = structBaseType; - } - } } else if (argObj->OperIs(GT_LCL_FLD, GT_IND)) { @@ -3473,6 +3437,36 @@ GenTreeCall* Compiler::fgMorphArgs(GenTreeCall* call) assert(varTypeIsEnregisterable(argObj->TypeGet()) || (makeOutArgCopy && varTypeIsEnregisterable(structBaseType))); } + +#if !defined(UNIX_AMD64_ABI) && !defined(TARGET_ARMARCH) && !defined(TARGET_LOONGARCH64) + // TODO-CQ-XARCH: there is no need for a temp copy if we improve our code generation in + // `genPutStructArgStk` for xarch like we did it for Arm/Arm64. + + // We still have a struct unless we converted the GT_OBJ into a GT_IND above... + if (isHfaArg && passUsingFloatRegs) + { + } + else if (structBaseType == TYP_STRUCT) + { + // If the valuetype size is not a multiple of TARGET_POINTER_SIZE, + // we must copyblk to a temp before doing the obj to avoid + // the obj reading memory past the end of the valuetype + if (roundupSize > originalSize) + { + makeOutArgCopy = true; + + // There are a few special cases where we can omit using a CopyBlk + // where we normally would need to use one. + + if (argObj->OperIs(GT_OBJ) && + argObj->AsObj()->gtGetOp1()->IsLocalAddrExpr() != nullptr) // Is the source a LclVar? + { + makeOutArgCopy = false; + } + } + } + +#endif // !UNIX_AMD64_ABI } } @@ -3806,15 +3800,15 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) #if FEATURE_MULTIREG_ARGS // Examine 'arg' and setup argValue objClass and structSize // - GenTree* argValue = argNode; // normally argValue will be arg, but see right below - ClassLayout* layout = nullptr; - unsigned structSize = 0; + const CORINFO_CLASS_HANDLE objClass = gtGetStructHandle(argNode); + GenTree* argValue = argNode; // normally argValue will be arg, but see right below + unsigned structSize = 0; if (argNode->OperGet() == GT_OBJ) { - GenTreeObj* argObj = argNode->AsObj(); - layout = argObj->GetLayout(); - structSize = layout->GetSize(); + GenTreeObj* argObj = argNode->AsObj(); + ClassLayout* objLayout = argObj->GetLayout(); + structSize = objLayout->GetSize(); // If we have a GT_OBJ of a GT_ADDR then we set argValue to the child node of the GT_ADDR. // TODO-ADDR: always perform this transformation in local morph and delete this code. @@ -3826,30 +3820,35 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) if (location->OperIsLocalRead()) { if (!location->OperIs(GT_LCL_VAR) || - !ClassLayout::AreCompatible(lvaGetDesc(location->AsLclVarCommon())->GetLayout(), layout)) + !ClassLayout::AreCompatible(lvaGetDesc(location->AsLclVarCommon())->GetLayout(), objLayout)) { unsigned lclOffset = location->AsLclVarCommon()->GetLclOffs(); location->ChangeType(argObj->TypeGet()); location->SetOper(GT_LCL_FLD); location->AsLclFld()->SetLclOffs(lclOffset); - location->AsLclFld()->SetLayout(layout); + location->AsLclFld()->SetLayout(objLayout); } argValue = location; } } } - else if (argNode->TypeIs(TYP_STRUCT)) + else if (argNode->OperGet() == GT_LCL_VAR) { - assert(argNode->OperIsLocalRead()); - layout = argNode->AsLclVarCommon()->GetLayout(this); - structSize = layout->GetSize(); + LclVarDsc* varDsc = lvaGetDesc(argNode->AsLclVarCommon()); + structSize = varDsc->lvExactSize; } - else + else if (!argNode->TypeIs(TYP_STRUCT)) { structSize = genTypeSize(argNode); } + else + { + structSize = info.compCompHnd->getClassSize(objClass); + } + + assert(structSize == info.compCompHnd->getClassSize(objClass)); struct ArgElem { @@ -3874,11 +3873,8 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) else { assert(structSize <= MAX_ARG_REG_COUNT * TARGET_POINTER_SIZE); - assert((layout != nullptr) || varTypeIsSIMD(argValue)); - - auto getSlotType = [layout](unsigned inx) { - return (layout != nullptr) ? layout->GetGCPtrType(inx) : TYP_I_IMPL; - }; + BYTE gcPtrs[MAX_ARG_REG_COUNT]; + info.compCompHnd->getClassGClayout(objClass, &gcPtrs[0]); // Here, we will set the sizes "rounded up" and then adjust the type of the last element below. for (unsigned inx = 0, offset = 0; inx < elemCount; inx++) @@ -3886,7 +3882,7 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) elems[inx].Offset = offset; #if defined(UNIX_AMD64_ABI) - if (!varTypeIsGC(getSlotType(inx))) + if (gcPtrs[inx] == TYPE_GC_NONE) { elems[inx].Type = GetTypeFromClassificationAndSizes(arg->AbiInfo.StructDesc.eightByteClassifications[inx], @@ -3903,7 +3899,7 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) else #endif // TARGET_LOONGARCH64 { - elems[inx].Type = getSlotType(inx); + elems[inx].Type = getJitGCType(gcPtrs[inx]); offset += TARGET_POINTER_SIZE; } } @@ -4057,10 +4053,11 @@ GenTree* Compiler::fgMorphMultiregStructArg(CallArg* arg) } else { - assert(argValue->OperIsIndir()); + assert(argValue->OperIs(GT_OBJ)); - GenTree* baseAddr = argValue->AsIndir()->Addr(); - var_types addrType = baseAddr->TypeGet(); + GenTreeObj* argObj = argValue->AsObj(); + GenTree* baseAddr = argObj->Addr(); + var_types addrType = baseAddr->TypeGet(); // TODO-ADDR: make sure all such OBJs are transformed into TYP_STRUCT LCL_FLDs and delete this condition. GenTreeLclVarCommon* lclSrcNode = baseAddr->IsLocalAddrExpr(); @@ -4161,7 +4158,7 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg) // // We don't need a copy if this is the last use of an implicit by-ref local. // - if (opts.OptimizationEnabled() && arg->AbiInfo.PassedByRef) + if (opts.OptimizationEnabled()) { GenTreeLclVar* const lcl = argx->IsImplicitByrefParameterValue(this); @@ -4223,7 +4220,7 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg) { tmp = (unsigned)lclNum; found = true; - JITDUMP("reusing outgoing struct arg\n"); + JITDUMP("reusing outgoing struct arg"); break; } } @@ -4270,7 +4267,7 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg) // When on Unix create LCL_FLD for structs passed in more than one registers. See fgMakeTmpArgNode GenTree* argNode = copyBlk; -#else // !FEATURE_FIXED_OUT_ARGS +#else // FEATURE_FIXED_OUT_ARGS // Structs are always on the stack, and thus never need temps // so we have to put the copy and temp all into one expression. @@ -4279,7 +4276,7 @@ void Compiler::fgMakeOutgoingStructArgCopy(GenTreeCall* call, CallArg* arg) // Change the expression to "(tmp=val),tmp" argNode = gtNewOperNode(GT_COMMA, argNode->TypeGet(), copyBlk, argNode); -#endif // !FEATURE_FIXED_OUT_ARGS +#endif // FEATURE_FIXED_OUT_ARGS arg->SetEarlyNode(argNode); } @@ -4645,11 +4642,10 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) // Likewise, allocate a temporary if the expression is a GT_LCL_FLD node. These used to be created // after fgMorphIndexAddr from GT_FIELD trees so this preserves the existing behavior. This is // perhaps a decision that should be left to CSE but FX diffs show that it is slightly better to - // do this here. Likewise for implicit byrefs. + // do this here. - if (((arrRef->gtFlags & (GTF_ASG | GTF_CALL | GTF_GLOB_REF)) != 0) || - gtComplexityExceeds(&arrRef, MAX_ARR_COMPLEXITY) || arrRef->OperIs(GT_FIELD, GT_LCL_FLD) || - (arrRef->OperIs(GT_LCL_VAR) && lvaIsLocalImplicitlyAccessedByRef(arrRef->AsLclVar()->GetLclNum()))) + if ((arrRef->gtFlags & (GTF_ASG | GTF_CALL | GTF_GLOB_REF)) || + gtComplexityExceeds(&arrRef, MAX_ARR_COMPLEXITY) || arrRef->OperIs(GT_FIELD, GT_LCL_FLD)) { unsigned arrRefTmpNum = lvaGrabTemp(true DEBUGARG("arr expr")); arrRefDefn = gtNewTempAssign(arrRefTmpNum, arrRef); @@ -4662,9 +4658,8 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) noway_assert(arrRef2 != nullptr); } - if (((index->gtFlags & (GTF_ASG | GTF_CALL | GTF_GLOB_REF)) != 0) || - gtComplexityExceeds(&index, MAX_ARR_COMPLEXITY) || index->OperIs(GT_FIELD, GT_LCL_FLD) || - (index->OperIs(GT_LCL_VAR) && lvaIsLocalImplicitlyAccessedByRef(index->AsLclVar()->GetLclNum()))) + if ((index->gtFlags & (GTF_ASG | GTF_CALL | GTF_GLOB_REF)) || gtComplexityExceeds(&index, MAX_ARR_COMPLEXITY) || + index->OperIs(GT_FIELD, GT_LCL_FLD)) { unsigned indexTmpNum = lvaGrabTemp(true DEBUGARG("index expr")); indexDefn = gtNewTempAssign(indexTmpNum, index); @@ -4770,8 +4765,8 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr) // we at least will be able to hoist/CSE "index + elemOffset" in some cases. // See https://github.com/dotnet/runtime/pull/61293#issuecomment-964146497 - // Don't use 2) for structs to reduce number of size regressions - if (varTypeIsStruct(elemTyp)) + // Use 2) form only for primitive types for now - it significantly reduced number of size regressions + if (!varTypeIsIntegral(elemTyp) && !varTypeIsFloating(elemTyp)) { groupArrayRefWithElemOffset = false; } @@ -4852,15 +4847,11 @@ GenTree* Compiler::fgMorphLocal(GenTreeLclVarCommon* lclNode) GenTree* expandedTree = nullptr; #ifdef TARGET_X86 expandedTree = fgMorphExpandStackArgForVarArgs(lclNode); -#else - expandedTree = fgMorphExpandImplicitByRefArg(lclNode); -#endif +#endif // TARGET_X86 if (expandedTree != nullptr) { - expandedTree = fgMorphTree(expandedTree); - DBEXEC(expandedTree == lclNode, expandedTree->gtDebugFlags &= ~GTF_DEBUG_NODE_MORPHED); - return expandedTree; + return fgMorphTree(expandedTree); } if (lclNode->OperIsLocalAddr()) @@ -4937,116 +4928,6 @@ GenTree* Compiler::fgMorphExpandStackArgForVarArgs(GenTreeLclVarCommon* lclNode) } #endif -//------------------------------------------------------------------------ -// fgMorphExpandImplicitByRefArg: Morph an implicit by-ref parameter. -// -// Arguments: -// lclNode - The local node to morph -// -// Return Value: -// The expanded tree for "lclNode", which the caller is expected to -// morph further. -// -GenTree* Compiler::fgMorphExpandImplicitByRefArg(GenTreeLclVarCommon* lclNode) -{ - if (!fgGlobalMorph) - { - return nullptr; - } - - unsigned lclNum = lclNode->GetLclNum(); - LclVarDsc* varDsc = lvaGetDesc(lclNum); - unsigned fieldOffset = 0; - unsigned newLclNum = BAD_VAR_NUM; - - if (lvaIsImplicitByRefLocal(lclNum)) - { - // The SIMD transformation to coalesce contiguous references to SIMD vector fields will re-invoke - // the traversal to mark address-taken locals. So, we may encounter a tree that has already been - // transformed to TYP_BYREF. If we do, leave it as-is. - if (lclNode->OperIs(GT_LCL_VAR) && lclNode->TypeIs(TYP_BYREF)) - { - return nullptr; - } - - if (varDsc->lvPromoted) - { - // fgRetypeImplicitByRefArgs created a new promoted struct local to represent this arg. - // Rewrite the node to refer to it. - assert(varDsc->lvFieldLclStart != 0); - - lclNode->SetLclNum(varDsc->lvFieldLclStart); - return lclNode; - } - - newLclNum = lclNum; - } - else if (varDsc->lvIsStructField && lvaIsImplicitByRefLocal(varDsc->lvParentLcl)) - { - // This was a field reference to an implicit-by-reference struct parameter that was - // dependently promoted. - newLclNum = varDsc->lvParentLcl; - fieldOffset = varDsc->lvFldOffset; - } - else - { - return nullptr; - } - - // Add a level of indirection to this node. The "base" will be a local node referring to "newLclNum". - // We will also add an offset, and, if the original "lclNode" represents a location, a dereference. - bool isAddress = lclNode->OperIsLocalAddr(); - unsigned offset = lclNode->GetLclOffs() + fieldOffset; - var_types argNodeType = lclNode->TypeGet(); - ClassLayout* argNodeLayout = nullptr; - if (varTypeIsStruct(argNodeType)) - { - argNodeLayout = lclNode->GetLayout(this); - } - - JITDUMP("\nRewriting an implicit by-ref parameter %s:\n", isAddress ? "address" : "reference"); - DISPTREE(lclNode); - - lclNode->ChangeType(TYP_BYREF); - lclNode->ChangeOper(GT_LCL_VAR); - lclNode->SetLclNum(newLclNum); - lclNode->SetAllEffectsFlags(GTF_EMPTY); // Implicit by-ref parameters cannot be address-exposed. - - GenTree* addrNode = lclNode; - if (offset != 0) - { - addrNode = gtNewOperNode(GT_ADD, TYP_BYREF, addrNode, gtNewIconNode(offset, TYP_I_IMPL)); - } - - GenTree* newArgNode; - if (!isAddress) - { - if (varTypeIsStruct(argNodeType)) - { - newArgNode = gtNewObjNode(argNodeLayout, addrNode); - } - else - { - newArgNode = gtNewIndir(argNodeType, addrNode); - } - - // Currently, we have to conservatively treat all indirections off of implicit byrefs as - // global. This is because we lose the information on whether the original local's address - // was exposed when we retype it in "fgRetypeImplicitByRefArgs". - newArgNode->gtFlags |= GTF_GLOB_REF; - } - else - { - newArgNode = addrNode; - } - - JITDUMP("Transformed into:\n"); - DISPTREE(newArgNode); - JITDUMP("\n"); - - return newArgNode; -} - /***************************************************************************** * * Transform the given GT_LCL_VAR tree for code generation. @@ -5155,12 +5036,21 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) CORINFO_FIELD_HANDLE symHnd = tree->AsField()->gtFldHnd; unsigned fldOffset = tree->AsField()->gtFldOffset; GenTree* objRef = tree->AsField()->GetFldObj(); + bool objIsLocal = false; bool fldMayOverlap = tree->AsField()->gtFldMayOverlap; FieldSeqNode* fieldSeq = FieldSeqStore::NotAField(); // Reset the flag because we may reuse the node. tree->AsField()->gtFldMayOverlap = false; + if (fgGlobalMorph && (objRef != nullptr) && (objRef->gtOper == GT_ADDR)) + { + // Make sure we've checked if 'objRef' is an address of an implicit-byref parameter. + // If it is, fgMorphImplicitByRefArgs may change it do a different opcode, which the + // simd field rewrites are sensitive to. + fgMorphImplicitByRefArgs(objRef); + } + noway_assert(((objRef != nullptr) && (objRef->IsLocalAddrExpr() != nullptr)) || ((tree->gtFlags & GTF_GLOB_REF) != 0)); @@ -5192,9 +5082,13 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) // before it is used. MorphAddrContext defMAC(MACK_Ind); - // Is this an instance data member? - if (objRef != nullptr) + /* Is this an instance data member? */ + + if (objRef) { + GenTree* addr; + objIsLocal = objRef->IsLocal(); + if (tree->gtFlags & GTF_IND_TLS_REF) { NO_WAY("instance field can not be a TLS ref."); @@ -5273,8 +5167,8 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) */ var_types objRefType = objRef->TypeGet(); - GenTree* addr = nullptr; - GenTree* comma = nullptr; + + GenTree* comma = nullptr; // NULL mac means we encounter the GT_FIELD first. This denotes a dereference of the field, // and thus is equivalent to a MACK_Ind with zero offset. @@ -5349,10 +5243,11 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) // Create the "comma" subtree // GenTree* asg = nullptr; + GenTree* nullchk; unsigned lclNum; - if (!objRef->OperIs(GT_LCL_VAR) || lvaIsLocalImplicitlyAccessedByRef(objRef->AsLclVar()->GetLclNum())) + if (objRef->gtOper != GT_LCL_VAR) { lclNum = fgGetBigOffsetMorphingTemp(genActualType(objRef->TypeGet())); @@ -5364,13 +5259,17 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) lclNum = objRef->AsLclVarCommon()->GetLclNum(); } - GenTree* lclVar = gtNewLclvNode(lclNum, objRefType); - GenTree* nullchk = gtNewNullCheck(lclVar, compCurBB); + GenTree* lclVar = gtNewLclvNode(lclNum, objRefType); + nullchk = gtNewNullCheck(lclVar, compCurBB); - if (asg != nullptr) + if (asg) { // Create the "comma" node. - comma = gtNewOperNode(GT_COMMA, TYP_VOID, asg, nullchk); + comma = gtNewOperNode(GT_COMMA, + TYP_VOID, // We don't want to return anything from this "comma" node. + // Set the type to TYP_VOID, so we can select "cmp" instruction + // instead of "mov" instruction later on. + asg, nullchk); } else { @@ -5595,8 +5494,7 @@ GenTree* Compiler::fgMorphField(GenTree* tree, MorphAddrContext* mac) { handleKind = GTF_ICON_STATIC_HDL; } - GenTreeIntCon* addr = gtNewIconHandleNode((size_t)fldAddr, handleKind, fieldSeq); - INDEBUG(addr->gtTargetHandle = reinterpret_cast(symHnd)); + GenTree* addr = gtNewIconHandleNode((size_t)fldAddr, handleKind, fieldSeq); // Translate GTF_FLD_INITCLASS to GTF_ICON_INITCLASS, if we need to. if (((tree->gtFlags & GTF_FLD_INITCLASS) != 0) && !isStaticReadOnlyInited) @@ -6751,11 +6649,9 @@ GenTree* Compiler::fgMorphPotentialTailCall(GenTreeCall* call) (call->gtCallType == CT_USER_FUNC) ? call->gtCallMethHnd : nullptr, call->IsTailPrefixedCall(), tailCallResult, nullptr); - // Do some profitability checks for whether we should expand a vtable call - // target early. Note that we may already have expanded it due to GDV at - // this point, so make sure we do not undo that work. + // Are we currently planning to expand the gtControlExpr as an early virtual call target? // - if (call->IsExpandedEarly() && call->IsVirtualVtable() && (call->gtControlExpr == nullptr)) + if (call->IsExpandedEarly() && call->IsVirtualVtable()) { assert(call->gtArgs.HasThisPointer()); // It isn't alway profitable to expand a virtual call early @@ -8022,7 +7918,7 @@ void Compiler::fgMorphTailCallViaJitHelper(GenTreeCall* call) // call - a call that needs virtual stub dispatching. // // Return Value: -// addr tree +// addr tree with set resister requirements. // GenTree* Compiler::fgGetStubAddrArg(GenTreeCall* call) { @@ -8037,9 +7933,12 @@ GenTree* Compiler::fgGetStubAddrArg(GenTreeCall* call) assert(call->gtCallMoreFlags & GTF_CALL_M_VIRTSTUB_REL_INDIRECT); ssize_t addr = ssize_t(call->gtStubCallStubAddr); stubAddrArg = gtNewIconHandleNode(addr, GTF_ICON_FTN_ADDR); - INDEBUG(stubAddrArg->AsIntCon()->gtTargetHandle = (size_t)call->gtCallMethHnd); +#ifdef DEBUG + stubAddrArg->AsIntCon()->gtTargetHandle = (size_t)call->gtCallMethHnd; +#endif } assert(stubAddrArg != nullptr); + stubAddrArg->SetRegNum(virtualStubParamInfo->GetReg()); return stubAddrArg; } @@ -8526,18 +8425,18 @@ GenTree* Compiler::fgMorphCall(GenTreeCall* call) // if (call->IsExpandedEarly() && call->IsVirtualVtable()) { - // We expand the Vtable Call target either in the global morph phase or - // in guarded devirt if we need it for the guard. - if (fgGlobalMorph && (call->gtControlExpr == nullptr)) + // We only expand the Vtable Call target once in the global morph phase + if (fgGlobalMorph) { + assert(call->gtControlExpr == nullptr); // We only call this method and assign gtControlExpr once call->gtControlExpr = fgExpandVirtualVtableCallTarget(call); } // We always have to morph or re-morph the control expr // call->gtControlExpr = fgMorphTree(call->gtControlExpr); - // Propagate any side effect flags into the call - call->gtFlags |= call->gtControlExpr->gtFlags & GTF_ALL_EFFECT; + // Propagate any gtFlags into the call + call->gtFlags |= call->gtControlExpr->gtFlags; } // Morph stelem.ref helper call to store a null value, into a store into an array without the helper. @@ -8923,8 +8822,7 @@ GenTree* Compiler::fgMorphLeaf(GenTree* tree) // target of a Delegate or a raw function pointer. bool isUnsafeFunctionPointer = !fptrValTree->gtFptrDelegateTarget; - CORINFO_CONST_LOOKUP addrInfo; - CORINFO_METHOD_HANDLE funcHandle = fptrValTree->gtFptrMethod; + CORINFO_CONST_LOOKUP addrInfo; #ifdef FEATURE_READYTORUN if (fptrValTree->gtEntryPoint.addr != nullptr) @@ -8934,7 +8832,7 @@ GenTree* Compiler::fgMorphLeaf(GenTree* tree) else #endif { - info.compCompHnd->getFunctionFixedEntryPoint(funcHandle, isUnsafeFunctionPointer, &addrInfo); + info.compCompHnd->getFunctionFixedEntryPoint(fptrValTree->gtFptrMethod, isUnsafeFunctionPointer, &addrInfo); } GenTree* indNode = nullptr; @@ -8953,7 +8851,6 @@ GenTree* Compiler::fgMorphLeaf(GenTree* tree) case IAT_PVALUE: indNode = gtNewIndOfIconHandleNode(TYP_I_IMPL, (size_t)addrInfo.handle, GTF_ICON_FTN_ADDR, true); - INDEBUG(indNode->gtGetOp1()->AsIntCon()->gtTargetHandle = reinterpret_cast(funcHandle)); break; case IAT_VALUE: @@ -8962,7 +8859,6 @@ GenTree* Compiler::fgMorphLeaf(GenTree* tree) tree->SetOper(GT_CNS_INT); tree->AsIntConCommon()->SetIconValue(ssize_t(addrInfo.handle)); tree->gtFlags |= GTF_ICON_FTN_ADDR; - INDEBUG(tree->AsIntCon()->gtTargetHandle = reinterpret_cast(funcHandle)); break; default: @@ -9725,11 +9621,6 @@ GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, ClassLa { lclNode = effectiveVal->AsLclVarCommon(); } - else if (effectiveVal->OperIs(GT_LCL_FLD)) - { - needsIndirection = false; - assert(ClassLayout::AreCompatible(effectiveVal->AsLclFld()->GetLayout(), blockLayout)); - } else if (effectiveVal->IsCall()) { needsIndirection = false; @@ -9978,7 +9869,7 @@ GenTree* Compiler::fgMorphFieldToSimdGetElement(GenTree* tree) var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); GenTree* op2 = gtNewIconNode(index, TYP_INT); - assert(simdSize <= 32); + assert(simdSize <= 16); assert(simdSize >= ((index + 1) * genTypeSize(simdBaseType))); #if defined(TARGET_XARCH) @@ -10053,7 +9944,7 @@ GenTree* Compiler::fgMorphFieldAssignToSimdSetElement(GenTree* tree) var_types simdType = simdStructNode->gtType; var_types simdBaseType = JitType2PreciseVarType(simdBaseJitType); - assert(simdSize <= 32); + assert(simdSize <= 16); assert(simdSize >= ((index + 1) * genTypeSize(simdBaseType))); GenTree* op2 = gtNewIconNode(index, TYP_INT); @@ -10069,6 +9960,18 @@ GenTree* Compiler::fgMorphFieldAssignToSimdSetElement(GenTree* tree) tree->AsOp()->gtOp1 = target; tree->AsOp()->gtOp2 = simdTree; + // fgMorphTree has already called fgMorphImplicitByRefArgs() on this assignment, but the source + // and target have not yet been morphed. + // Therefore, in case the source and/or target are now implicit byrefs, we need to call it again. + if (fgMorphImplicitByRefArgs(tree)) + { + if (tree->gtGetOp1()->OperIsBlk()) + { + assert(tree->gtGetOp1()->TypeGet() == simdType); + tree->gtGetOp1()->SetOper(GT_IND); + tree->gtGetOp1()->gtType = simdType; + } + } #ifdef DEBUG tree->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED; #endif @@ -10381,6 +10284,22 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) case GT_MUL: noway_assert(op2 != nullptr); + if (opts.OptimizationEnabled() && !optValnumCSE_phase && !tree->gtOverflow()) + { + // MUL(NEG(a), C) => MUL(a, NEG(C)) + if (op1->OperIs(GT_NEG) && !op1->gtGetOp1()->IsCnsIntOrI() && op2->IsCnsIntOrI() && + !op2->IsIconHandle()) + { + GenTree* newOp1 = op1->gtGetOp1(); + GenTree* newConst = gtNewIconNode(-op2->AsIntCon()->IconValue(), op2->TypeGet()); + DEBUG_DESTROY_NODE(op1); + DEBUG_DESTROY_NODE(op2); + tree->AsOp()->gtOp1 = newOp1; + tree->AsOp()->gtOp2 = newConst; + return fgMorphSmpOp(tree, mac); + } + } + #ifndef TARGET_64BIT if (typ == TYP_LONG) { @@ -10641,7 +10560,10 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) #ifdef TARGET_ARM64 // ARM64 architecture manual suggests this transformation // for the mod operator. - else + // However, we do skip this optimization for ARM64 if the second operand + // is an integral constant power of 2 because there is an even better + // optimization in lowering that is specific for ARM64. + else if (!(tree->OperIs(GT_MOD) && op2->IsIntegralConstPow2())) #else // XARCH only applies this transformation if we know // that magic division will be used - which is determined @@ -11291,7 +11213,9 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) */ GenTree* temp; + size_t ival1; GenTree* lclVarTree; + GenTree* effectiveOp1; FieldSeqNode* fieldSeq = nullptr; switch (oper) @@ -11311,14 +11235,28 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) lclVarTree->gtFlags |= GTF_VAR_DEF; } - if (op2->OperIs(GT_CAST)) + effectiveOp1 = op1->gtEffectiveVal(); + + // If we are storing a small type, we might be able to omit a cast. + if ((effectiveOp1->OperIs(GT_IND) || + (effectiveOp1->OperIs(GT_LCL_VAR) && + lvaGetDesc(effectiveOp1->AsLclVarCommon()->GetLclNum())->lvNormalizeOnLoad())) && + varTypeIsSmall(effectiveOp1)) { - tree = fgOptimizeCastOnAssignment(tree->AsOp()); + if (!gtIsActiveCSE_Candidate(op2) && op2->OperIs(GT_CAST) && + varTypeIsIntegral(op2->AsCast()->CastOp()) && !op2->gtOverflow()) + { + var_types castType = op2->CastToType(); - assert(tree->OperIs(GT_ASG)); + // If we are performing a narrowing cast and + // castType is larger or the same as op1's type + // then we can discard the cast. - op1 = tree->gtGetOp1(); - op2 = tree->gtGetOp2(); + if (varTypeIsSmall(castType) && (genTypeSize(castType) >= genTypeSize(effectiveOp1))) + { + tree->AsOp()->gtOp2 = op2 = op2->AsCast()->CastOp(); + } + } } fgAssignSetVarDef(tree); @@ -11385,21 +11323,6 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) assert(op2 == tree->AsOp()->gtGetOp2()); } - if (opts.OptimizationEnabled() && fgGlobalMorph) - { - if (op2->IsIntegralConst() || op1->IsIntegralConst()) - { - if (tree->OperIs(GT_GT, GT_LT, GT_LE, GT_GE)) - { - tree = fgOptimizeRelationalComparisonWithFullRangeConst(tree->AsOp()); - if (tree->OperIs(GT_CNS_INT)) - { - return tree; - } - } - } - } - COMPARE: noway_assert(tree->OperIsCompare()); @@ -11667,14 +11590,15 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) bool foldAndReturnTemp = false; temp = nullptr; + ival1 = 0; // Don't remove a volatile GT_IND, even if the address points to a local variable. - // - if (!tree->AsIndir()->IsVolatile()) + if ((tree->gtFlags & GTF_IND_VOLATILE) == 0) { /* Try to Fold *(&X) into X */ if (op1->gtOper == GT_ADDR) { + // Can not remove a GT_ADDR if it is currently a CSE candidate. if (gtIsActiveCSE_Candidate(op1)) { break; @@ -11774,34 +11698,98 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) } } #endif // TARGET_ARM + + /* Try to change *(&lcl + cns) into lcl[cns] to prevent materialization of &lcl */ + + if (op1->AsOp()->gtOp1->OperGet() == GT_ADDR && op1->AsOp()->gtOp2->OperGet() == GT_CNS_INT && + opts.OptimizationEnabled()) + { + // No overflow arithmetic with pointers + noway_assert(!op1->gtOverflow()); + + temp = op1->AsOp()->gtOp1->AsOp()->gtOp1; + if (!temp->OperIsLocal()) + { + temp = nullptr; + break; + } + + // Can not remove the GT_ADDR if it is currently a CSE candidate. + if (gtIsActiveCSE_Candidate(op1->AsOp()->gtOp1)) + { + break; + } + + ival1 = op1->AsOp()->gtOp2->AsIntCon()->gtIconVal; + fieldSeq = op1->AsOp()->gtOp2->AsIntCon()->gtFieldSeq; + + if (ival1 == 0 && typ == temp->TypeGet() && temp->TypeGet() != TYP_STRUCT) + { + noway_assert(!varTypeIsGC(temp->TypeGet())); + foldAndReturnTemp = true; + } + else + { + // The emitter can't handle large offsets + if (ival1 != (unsigned short)ival1) + { + break; + } + + // The emitter can get confused by invalid offsets + if (ival1 >= Compiler::lvaLclSize(temp->AsLclVarCommon()->GetLclNum())) + { + break; + } + } + // Now we can fold this into a GT_LCL_FLD below + // where we check (temp != nullptr) + } } } - // At this point we may have a lclVar or lclFld of some mismatched type. In this case, we will change - // the lclVar or lclFld into a lclFld of the appropriate type if doing so is legal. The only cases in - // which this transformation is illegal is when we have a STRUCT indirection, as we do not have the - // necessary layout information, or if the load would extend beyond the local. + // At this point we may have a lclVar or lclFld that might be foldable with a bit of extra massaging: + // - We may have a load of a local where the load has a different type than the local + // - We may have a load of a local plus an offset + // + // In these cases, we will change the lclVar or lclFld into a lclFld of the appropriate type and + // offset if doing so is legal. The only cases in which this transformation is illegal are if the load + // begins before the local or if the load extends beyond the end of the local (i.e. if the load is + // out-of-bounds w.r.t. the local). if ((temp != nullptr) && !foldAndReturnTemp) { - assert(temp->OperIs(GT_LCL_VAR, GT_LCL_FLD)); + assert(temp->OperIsLocal()); - unsigned lclNum = temp->AsLclVarCommon()->GetLclNum(); - unsigned lclOffs = temp->AsLclVarCommon()->GetLclOffs(); + unsigned lclNum = temp->AsLclVarCommon()->GetLclNum(); // Make sure we do not enregister this lclVar. lvaSetVarDoNotEnregister(lclNum DEBUGARG(DoNotEnregisterReason::LocalField)); - if ((typ != TYP_STRUCT) && ((lclOffs + genTypeSize(typ)) <= lvaLclExactSize(lclNum))) + // If the size of the load is greater than the size of the lclVar, we cannot fold this access into + // a lclFld: the access represented by an lclFld node must begin at or after the start of the + // lclVar and must not extend beyond the end of the lclVar. + if ((ival1 >= 0) && ((ival1 + genTypeSize(typ)) <= lvaLclExactSize(lclNum))) { - // We will change the type of the node to match the orginal GT_IND type. - // - temp->gtType = typ; + GenTreeLclFld* lclFld; - if (temp->OperIs(GT_LCL_VAR)) + // We will turn a GT_LCL_VAR into a GT_LCL_FLD with an gtLclOffs of 'ival' + // or if we already have a GT_LCL_FLD we will adjust the gtLclOffs by adding 'ival' + // Then we change the type of the GT_LCL_FLD to match the orginal GT_IND type. + // + if (temp->OperGet() == GT_LCL_FLD) + { + lclFld = temp->AsLclFld(); + lclFld->SetLclOffs(lclFld->GetLclOffs() + static_cast(ival1)); + } + else // We have a GT_LCL_VAR. { - temp->ChangeOper(GT_LCL_FLD); + assert(temp->OperGet() == GT_LCL_VAR); + temp->ChangeOper(GT_LCL_FLD); // Note that this makes the gtFieldSeq "NotAField". + lclFld = temp->AsLclFld(); + lclFld->SetLclOffs(static_cast(ival1)); } + temp->gtType = tree->gtType; foldAndReturnTemp = true; } } @@ -11810,7 +11798,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) { assert(temp != nullptr); assert(temp->TypeGet() == typ); - assert(op1->OperIs(GT_ADDR)); + assert((op1->OperGet() == GT_ADD) || (op1->OperGet() == GT_ADDR)); // Copy the value of GTF_DONT_CSE from the original tree to `temp`: it can be set for // 'temp' because a GT_ADDR always marks it for its operand. @@ -11818,7 +11806,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac) temp->gtFlags |= (tree->gtFlags & GTF_DONT_CSE); temp->SetVNsFromNode(tree); - DEBUG_DESTROY_NODE(op1); // GT_ADDR + if (op1->OperGet() == GT_ADD) + { + DEBUG_DESTROY_NODE(op1->AsOp()->gtOp1); // GT_ADDR + DEBUG_DESTROY_NODE(op1->AsOp()->gtOp2); // GT_CNS_INT + } + DEBUG_DESTROY_NODE(op1); // GT_ADD or GT_ADDR DEBUG_DESTROY_NODE(tree); // GT_IND // If the result of the fold is a local var, we may need to perform further adjustments e.g. for @@ -12300,75 +12293,6 @@ GenTree* Compiler::fgOptimizeCast(GenTreeCast* cast) return cast; } -//------------------------------------------------------------------------ -// fgOptimizeCastOnAssignment: Optimizes the supplied GT_ASG tree with a GT_CAST node. -// -// Arguments: -// tree - the cast tree to optimize -// -// Return Value: -// The optimized tree (must be GT_ASG). -// -GenTree* Compiler::fgOptimizeCastOnAssignment(GenTreeOp* asg) -{ - assert(asg->OperIs(GT_ASG)); - - GenTree* const op1 = asg->gtGetOp1(); - GenTree* const op2 = asg->gtGetOp2(); - - assert(op2->OperIs(GT_CAST)); - - GenTree* const effectiveOp1 = op1->gtEffectiveVal(); - - if (!effectiveOp1->OperIs(GT_IND, GT_LCL_VAR)) - return asg; - - if (effectiveOp1->OperIs(GT_LCL_VAR) && - !lvaGetDesc(effectiveOp1->AsLclVarCommon()->GetLclNum())->lvNormalizeOnLoad()) - return asg; - - if (op2->gtOverflow()) - return asg; - - if (gtIsActiveCSE_Candidate(op2)) - return asg; - - GenTreeCast* cast = op2->AsCast(); - var_types castToType = cast->CastToType(); - var_types castFromType = cast->CastFromType(); - - if (gtIsActiveCSE_Candidate(cast->CastOp())) - return asg; - - if (!varTypeIsSmall(effectiveOp1)) - return asg; - - if (!varTypeIsSmall(castToType)) - return asg; - - if (!varTypeIsIntegral(castFromType)) - return asg; - - // If we are performing a narrowing cast and - // castToType is larger or the same as op1's type - // then we can discard the cast. - if (genTypeSize(castToType) < genTypeSize(effectiveOp1)) - return asg; - - if (genActualType(castFromType) == genActualType(castToType)) - { - // Removes the cast. - asg->gtOp2 = cast->CastOp(); - } - else - { - // This is a type-changing cast so we cannot remove it entirely. - cast->gtCastType = genActualType(castToType); - } - - return asg; -} - //------------------------------------------------------------------------ // fgOptimizeEqualityComparisonWithConst: optimizes various EQ/NE(OP, CONST) patterns. // @@ -12605,123 +12529,6 @@ GenTree* Compiler::fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp) return cmp; } -//------------------------------------------------------------------------ -// fgOptimizeRelationalComparisonWithFullRangeConst: optimizes a comparison operation. -// -// Recognizes "Always false"/"Always true" comparisons against various full range constant operands and morphs -// them into zero/one. -// -// Arguments: -// cmp - the GT_LT/GT_GT tree to morph. -// -// Return Value: -// 1. The unmodified "cmp" tree. -// 2. A CNS_INT node containing zero. -// 3. A CNS_INT node containing one. -// Assumptions: -// The second operand is an integral constant or the first operand is an integral constant. -// -GenTree* Compiler::fgOptimizeRelationalComparisonWithFullRangeConst(GenTreeOp* cmp) -{ - if (gtTreeHasSideEffects(cmp, GTF_SIDE_EFFECT)) - { - return cmp; - } - - int64_t lhsMin; - int64_t lhsMax; - if (cmp->gtGetOp1()->IsIntegralConst()) - { - lhsMin = cmp->gtGetOp1()->AsIntConCommon()->IntegralValue(); - lhsMax = lhsMin; - } - else - { - IntegralRange lhsRange = IntegralRange::ForNode(cmp->gtGetOp1(), this); - lhsMin = IntegralRange::SymbolicToRealValue(lhsRange.GetLowerBound()); - lhsMax = IntegralRange::SymbolicToRealValue(lhsRange.GetUpperBound()); - } - - int64_t rhsMin; - int64_t rhsMax; - if (cmp->gtGetOp2()->IsIntegralConst()) - { - rhsMin = cmp->gtGetOp2()->AsIntConCommon()->IntegralValue(); - rhsMax = rhsMin; - } - else - { - IntegralRange rhsRange = IntegralRange::ForNode(cmp->gtGetOp2(), this); - rhsMin = IntegralRange::SymbolicToRealValue(rhsRange.GetLowerBound()); - rhsMax = IntegralRange::SymbolicToRealValue(rhsRange.GetUpperBound()); - } - - genTreeOps op = cmp->gtOper; - if ((op != GT_LT) && (op != GT_LE)) - { - op = GenTree::SwapRelop(op); - std::swap(lhsMin, rhsMin); - std::swap(lhsMax, rhsMax); - } - - GenTree* ret = nullptr; - - if (cmp->IsUnsigned()) - { - if ((lhsMin < 0) && (lhsMax >= 0)) - { - // [0, (uint64_t)lhsMax] U [(uint64_t)lhsMin, MaxValue] - lhsMin = 0; - lhsMax = -1; - } - - if ((rhsMin < 0) && (rhsMax >= 0)) - { - // [0, (uint64_t)rhsMax] U [(uint64_t)rhsMin, MaxValue] - rhsMin = 0; - rhsMax = -1; - } - - if (((op == GT_LT) && ((uint64_t)lhsMax < (uint64_t)rhsMin)) || - ((op == GT_LE) && ((uint64_t)lhsMax <= (uint64_t)rhsMin))) - { - ret = gtNewOneConNode(TYP_INT); - } - else if (((op == GT_LT) && ((uint64_t)lhsMin >= (uint64_t)rhsMax)) || - ((op == GT_LE) && ((uint64_t)lhsMin > (uint64_t)rhsMax))) - { - ret = gtNewZeroConNode(TYP_INT); - } - } - else - { - // [x0, x1] < [y0, y1] is false if x0 >= y1 - // [x0, x1] <= [y0, y1] is false if x0 > y1 - if (((op == GT_LT) && (lhsMin >= rhsMax)) || (((op == GT_LE) && (lhsMin > rhsMax)))) - { - ret = gtNewZeroConNode(TYP_INT); - } - // [x0, x1] < [y0, y1] is true if x1 < y0 - else if ((op == GT_LT) && (lhsMax < rhsMin)) - { - ret = gtNewOneConNode(TYP_INT); - } - } - - if (ret != nullptr) - { - fgUpdateConstTreeValueNumber(ret); - - DEBUG_DESTROY_NODE(cmp); - - INDEBUG(ret->gtDebugFlags |= GTF_DEBUG_NODE_MORPHED); - - return ret; - } - - return cmp; -} - //------------------------------------------------------------------------ // fgOptimizeRelationalComparisonWithConst: optimizes a comparison operation. // @@ -13006,39 +12813,9 @@ GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add) return op1; } + // Note that these transformations are legal for floating-point ADDs as well. if (opts.OptimizationEnabled()) { - // Reduce local addresses: "ADD(ADDR(LCL_VAR), OFFSET)" => "ADDR(LCL_FLD OFFSET)". - // TODO-ADDR: do "ADD(LCL_FLD/VAR_ADDR, OFFSET)" => "LCL_FLD_ADDR" instead. - // - if (op1->OperIs(GT_ADDR) && op2->IsCnsIntOrI() && op1->gtGetOp1()->OperIsLocalRead()) - { - GenTreeUnOp* addrNode = op1->AsUnOp(); - GenTreeLclVarCommon* lclNode = addrNode->gtGetOp1()->AsLclVarCommon(); - GenTreeIntCon* offsetNode = op2->AsIntCon(); - if (FitsIn(offsetNode->IconValue())) - { - unsigned offset = lclNode->GetLclOffs() + static_cast(offsetNode->IconValue()); - - // Note: the emitter does not expect out-of-bounds access for LCL_FLD_ADDR. - if (FitsIn(offset) && (offset < lvaLclExactSize(lclNode->GetLclNum()))) - { - // Types of location nodes under ADDRs do not matter. We arbitrarily choose TYP_UBYTE. - lclNode->ChangeType(TYP_UBYTE); - lclNode->SetOper(GT_LCL_FLD); - lclNode->AsLclFld()->SetLclOffs(offset); - lvaSetVarDoNotEnregister(lclNode->GetLclNum() DEBUGARG(DoNotEnregisterReason::LocalField)); - - addrNode->SetVNsFromNode(add); - - DEBUG_DESTROY_NODE(offsetNode); - DEBUG_DESTROY_NODE(add); - - return addrNode; - } - } - } - // - a + b = > b - a // ADD((NEG(a), b) => SUB(b, a) @@ -13133,20 +12910,6 @@ GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul) if (op2->IsIntegralConst()) { - // We should not get here for 64-bit multiplications on 32-bit. - assert(op2->IsCnsIntOrI()); - - // MUL(NEG(a), C) => MUL(a, NEG(C)) - if (opts.OptimizationEnabled() && op1->OperIs(GT_NEG) && !op2->IsIconHandle()) - { - mul->gtOp1 = op1->AsUnOp()->gtGetOp1(); - op2->AsIntCon()->gtIconVal = -op2->AsIntCon()->gtIconVal; - fgUpdateConstTreeValueNumber(op2); - DEBUG_DESTROY_NODE(op1); - - op1 = mul->gtOp1; - } - ssize_t mult = op2->AsIntConCommon()->IconValue(); if (mult == 0) @@ -13523,19 +13286,41 @@ GenTree* Compiler::fgMorphRetInd(GenTreeUnOp* ret) if (addr->OperIs(GT_ADDR) && addr->gtGetOp1()->OperIs(GT_LCL_VAR)) { + // If struct promotion was undone, adjust the annotations + if (fgGlobalMorph && fgMorphImplicitByRefArgs(addr)) + { + return ind; + } + // If `return` retypes LCL_VAR as a smaller struct it should not set `doNotEnregister` on that // LclVar. // Example: in `Vector128:AsVector2` we have RETURN SIMD8(OBJ SIMD8(ADDR byref(LCL_VAR SIMD16))). GenTreeLclVar* lclVar = addr->gtGetOp1()->AsLclVar(); - if (!lvaIsImplicitByRefLocal(lclVar->GetLclNum())) { assert(!gtIsActiveCSE_Candidate(addr) && !gtIsActiveCSE_Candidate(ind)); + unsigned indSize; + if (ind->OperIs(GT_IND)) + { + indSize = genTypeSize(ind); + } + else + { + indSize = ind->AsBlk()->GetLayout()->GetSize(); + } + + LclVarDsc* varDsc = lvaGetDesc(lclVar); - LclVarDsc* varDsc = lvaGetDesc(lclVar); - unsigned indSize = ind->Size(); - unsigned lclVarSize = lvaLclExactSize(lclVar->GetLclNum()); + unsigned lclVarSize; + if (!lclVar->TypeIs(TYP_STRUCT)) + { + lclVarSize = genTypeSize(varDsc->TypeGet()); + } + else + { + lclVarSize = varDsc->lvExactSize; + } // TODO: change conditions in `canFold` to `indSize <= lclVarSize`, but currently do not support `BITCAST // int<-SIMD16` etc. assert((indSize <= lclVarSize) || varDsc->lvDoNotEnregister); @@ -13570,7 +13355,6 @@ GenTree* Compiler::fgMorphRetInd(GenTreeUnOp* ret) } } } - return ind; } @@ -14474,6 +14258,23 @@ GenTree* Compiler::fgMorphTree(GenTree* tree, MorphAddrContext* mac) } #endif + if (fgGlobalMorph) + { + // Apply any rewrites for implicit byref arguments before morphing the + // tree. + + if (fgMorphImplicitByRefArgs(tree)) + { +#ifdef DEBUG + if (verbose && treesBeforeAfterMorph) + { + printf("\nfgMorphTree (%d), after implicit-byref rewrite:\n", thisMorphNum); + gtDispTree(tree); + } +#endif + } + } + /*------------------------------------------------------------------------- * fgMorphTree() can potentially replace a tree with another, and the * caller has to store the return value correctly. @@ -15123,16 +14924,18 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) noway_assert(lastStmt->GetRootNode()->gtOper == GT_SWITCH); - // Did we fold the conditional + /* Did we fold the conditional */ noway_assert(lastStmt->GetRootNode()->AsOp()->gtOp1); - GenTree* condTree = lastStmt->GetRootNode()->AsOp()->gtOp1; - GenTree* cond = condTree->gtEffectiveVal(true); + GenTree* condTree; + condTree = lastStmt->GetRootNode()->AsOp()->gtOp1; + GenTree* cond; + cond = condTree->gtEffectiveVal(true); if (cond->OperIsConst()) { - // Yupee - we folded the conditional! - // Remove the conditional statement + /* Yupee - we folded the conditional! + * Remove the conditional statement */ noway_assert(cond->gtOper == GT_CNS_INT); @@ -15150,13 +14953,17 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) result = FoldResult::FOLD_REMOVED_LAST_STMT; } - // modify the flow graph + /* modify the flow graph */ - // Find the actual jump target - size_t switchVal = (size_t)cond->AsIntCon()->gtIconVal; - unsigned jumpCnt = block->bbJumpSwt->bbsCount; - BasicBlock** jumpTab = block->bbJumpSwt->bbsDstTab; - bool foundVal = false; + /* Find the actual jump target */ + unsigned switchVal; + switchVal = (unsigned)cond->AsIntCon()->gtIconVal; + unsigned jumpCnt; + jumpCnt = block->bbJumpSwt->bbsCount; + BasicBlock** jumpTab; + jumpTab = block->bbJumpSwt->bbsDstTab; + bool foundVal; + foundVal = false; for (unsigned val = 0; val < jumpCnt; val++, jumpTab++) { @@ -15171,20 +14978,20 @@ Compiler::FoldResult Compiler::fgFoldConditional(BasicBlock* block) { if (curJump != block->bbNext) { - // transform the basic block into a BBJ_ALWAYS + /* transform the basic block into a BBJ_ALWAYS */ block->bbJumpKind = BBJ_ALWAYS; block->bbJumpDest = curJump; } else { - // transform the basic block into a BBJ_NONE + /* transform the basic block into a BBJ_NONE */ block->bbJumpKind = BBJ_NONE; } foundVal = true; } else { - // Remove 'block' from the predecessor list of 'curJump' + /* Remove 'block' from the predecessor list of 'curJump' */ fgRemoveRefPred(curJump, block); } } @@ -16895,7 +16702,7 @@ void Compiler::fgMorphLocalField(GenTree* tree, GenTree* parent) void Compiler::fgResetImplicitByRefRefCount() { -#if FEATURE_IMPLICIT_BYREFS +#if (defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI)) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) #ifdef DEBUG if (verbose) { @@ -16918,7 +16725,7 @@ void Compiler::fgResetImplicitByRefRefCount() } } -#endif // FEATURE_IMPLICIT_BYREFS +#endif // (TARGET_AMD64 && !UNIX_AMD64_ABI) || TARGET_ARM64 || TARGET_LOONGARCH64 } //------------------------------------------------------------------------ @@ -16927,12 +16734,12 @@ void Compiler::fgResetImplicitByRefRefCount() // which struct promotions of implicit byrefs to keep or discard. // For those which are kept, insert the appropriate initialization code. // For those which are to be discarded, annotate the promoted field locals -// so that fgMorphExpandImplicitByRefArg will know to rewrite their -// appearances using indirections off the pointer parameters. -// +// so that fgMorphImplicitByRefArgs will know to rewrite their appearances +// using indirections off the pointer parameters. + void Compiler::fgRetypeImplicitByRefArgs() { -#if FEATURE_IMPLICIT_BYREFS +#if (defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI)) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) #ifdef DEBUG if (verbose) { @@ -17053,7 +16860,7 @@ void Compiler::fgRetypeImplicitByRefArgs() if (undoPromotion) { - // Leave lvParentLcl pointing to the parameter so that fgMorphExpandImplicitByRefArg + // Leave lvParentLcl pointing to the parameter so that fgMorphImplicitByRefArgs // will know to rewrite appearances of this local. assert(fieldVarDsc->lvParentLcl == lclNum); } @@ -17090,7 +16897,7 @@ void Compiler::fgRetypeImplicitByRefArgs() // have these fields. varDsc->lvFieldCnt = 0; - // Hijack lvPromoted to communicate to fgMorphExpandImplicitByRefArg + // Hijack lvPromoted to communicate to fgMorphImplicitByRefArgs // whether references to the struct should be rewritten as // indirections off the pointer (not promoted) or references // to the new struct local (promoted). @@ -17102,10 +16909,10 @@ void Compiler::fgRetypeImplicitByRefArgs() // promotion wanted to promote but that aren't considered profitable to // rewrite. It hijacks lvFieldLclStart to communicate to // fgMarkDemotedImplicitByRefArgs that it needs to clean up annotations left - // on such args for fgMorphExpandImplicitByRefArg to consult in the interim. + // on such args for fgMorphImplicitByRefArgs to consult in the interim. // Here we have an arg that was simply never promoted, so make sure it doesn't - // have nonzero lvFieldLclStart, since that would confuse the aforementioned - // functions. + // have nonzero lvFieldLclStart, since that would confuse fgMorphImplicitByRefArgs + // and fgMarkDemotedImplicitByRefArgs. assert(varDsc->lvFieldLclStart == 0); } @@ -17138,21 +16945,20 @@ void Compiler::fgRetypeImplicitByRefArgs() } } -#endif // FEATURE_IMPLICIT_BYREFS +#endif // (TARGET_AMD64 && !UNIX_AMD64_ABI) || TARGET_ARM64 || TARGET_LOONGARCH64 } //------------------------------------------------------------------------ // fgMarkDemotedImplicitByRefArgs: Clear annotations for any implicit byrefs that struct promotion // asked to promote. Appearances of these have now been rewritten -// (by fgMorphExpandImplicitByRefArg) using indirections from -// the pointer parameter or references to the promotion temp, as -// appropriate. -// +// (by fgMorphImplicitByRefArgs) using indirections from the pointer +// parameter or references to the promotion temp, as appropriate. + void Compiler::fgMarkDemotedImplicitByRefArgs() { JITDUMP("\n*************** In fgMarkDemotedImplicitByRefArgs()\n"); -#if FEATURE_IMPLICIT_BYREFS +#if (defined(TARGET_AMD64) && !defined(UNIX_AMD64_ABI)) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) for (unsigned lclNum = 0; lclNum < info.compArgsCount; lclNum++) { @@ -17164,13 +16970,13 @@ void Compiler::fgMarkDemotedImplicitByRefArgs() if (varDsc->lvPromoted) { - // The parameter is simply a pointer now, so clear lvPromoted. It was left set by - // fgRetypeImplicitByRefArgs to communicate to fgMorphExpandImplicitByRefArg that + // The parameter is simply a pointer now, so clear lvPromoted. It was left set + // by fgRetypeImplicitByRefArgs to communicate to fgMorphImplicitByRefArgs that // appearances of this arg needed to be rewritten to a new promoted struct local. varDsc->lvPromoted = false; // Clear the lvFieldLclStart value that was set by fgRetypeImplicitByRefArgs - // to tell fgMorphExpandImplicitByRefArg which local is the new promoted struct one. + // to tell fgMorphImplicitByRefArgs which local is the new promoted struct one. varDsc->lvFieldLclStart = 0; } else if (varDsc->lvFieldLclStart != 0) @@ -17213,7 +17019,181 @@ void Compiler::fgMarkDemotedImplicitByRefArgs() } } -#endif // FEATURE_IMPLICIT_BYREFS +#endif // (TARGET_AMD64 && !UNIX_AMD64_ABI) || TARGET_ARM64 || TARGET_LOONGARCH64 +} + +/***************************************************************************** + * + * Morph irregular parameters + * for x64 and ARM64 this means turning them into byrefs, adding extra indirs. + */ +bool Compiler::fgMorphImplicitByRefArgs(GenTree* tree) +{ +#if (!defined(TARGET_AMD64) || defined(UNIX_AMD64_ABI)) && !defined(TARGET_ARM64) && !defined(TARGET_LOONGARCH64) + + return false; + +#else // (TARGET_AMD64 && !UNIX_AMD64_ABI) || TARGET_ARM64 || TARGET_LOONGARCH64 + + bool changed = false; + + // Implicit byref morphing needs to know if the reference to the parameter is a + // child of GT_ADDR or not, so this method looks one level down and does the + // rewrite whenever a child is a reference to an implicit byref parameter. + if (tree->gtOper == GT_ADDR) + { + if (tree->AsOp()->gtOp1->gtOper == GT_LCL_VAR) + { + GenTree* morphedTree = fgMorphImplicitByRefArgs(tree, true); + changed = (morphedTree != nullptr); + assert(!changed || (morphedTree == tree)); + } + } + else + { + for (GenTree** pTree : tree->UseEdges()) + { + GenTree** pTreeCopy = pTree; + GenTree* childTree = *pTree; + if (childTree->gtOper == GT_LCL_VAR) + { + GenTree* newChildTree = fgMorphImplicitByRefArgs(childTree, false); + if (newChildTree != nullptr) + { + changed = true; + *pTreeCopy = newChildTree; + } + } + } + } + + return changed; +#endif // (TARGET_AMD64 && !UNIX_AMD64_ABI) || TARGET_ARM64 || TARGET_LOONGARCH64 +} + +GenTree* Compiler::fgMorphImplicitByRefArgs(GenTree* tree, bool isAddr) +{ + assert((tree->gtOper == GT_LCL_VAR) || ((tree->gtOper == GT_ADDR) && (tree->AsOp()->gtOp1->gtOper == GT_LCL_VAR))); + assert(isAddr == (tree->gtOper == GT_ADDR)); + + GenTree* lclVarTree = isAddr ? tree->AsOp()->gtOp1 : tree; + unsigned lclNum = lclVarTree->AsLclVarCommon()->GetLclNum(); + LclVarDsc* lclVarDsc = lvaGetDesc(lclNum); + + CORINFO_FIELD_HANDLE fieldHnd; + unsigned fieldOffset = 0; + var_types fieldRefType = TYP_UNKNOWN; + + if (lvaIsImplicitByRefLocal(lclNum)) + { + // The SIMD transformation to coalesce contiguous references to SIMD vector fields will + // re-invoke the traversal to mark address-taken locals. + // So, we may encounter a tree that has already been transformed to TYP_BYREF. + // If we do, leave it as-is. + if (!varTypeIsStruct(lclVarTree)) + { + assert(lclVarTree->TypeGet() == TYP_BYREF); + + return nullptr; + } + else if (lclVarDsc->lvPromoted) + { + // fgRetypeImplicitByRefArgs created a new promoted struct local to represent this + // arg. Rewrite this to refer to the new local. + assert(lclVarDsc->lvFieldLclStart != 0); + lclVarTree->AsLclVarCommon()->SetLclNum(lclVarDsc->lvFieldLclStart); + return tree; + } + + fieldHnd = nullptr; + } + else if (lclVarDsc->lvIsStructField && lvaIsImplicitByRefLocal(lclVarDsc->lvParentLcl)) + { + // This was a field reference to an implicit-by-reference struct parameter that was + // dependently promoted; update it to a field reference off the pointer. + // Grab the field handle from the struct field lclVar. + fieldHnd = lclVarDsc->lvFieldHnd; + fieldOffset = lclVarDsc->lvFldOffset; + assert(fieldHnd != nullptr); + // Update lclNum/lclVarDsc to refer to the parameter + lclNum = lclVarDsc->lvParentLcl; + lclVarDsc = lvaGetDesc(lclNum); + fieldRefType = lclVarTree->TypeGet(); + } + else + { + // We only need to tranform the 'marked' implicit by ref parameters + return nullptr; + } + + // This is no longer a def of the lclVar, even if it WAS a def of the struct. + lclVarTree->gtFlags &= ~(GTF_LIVENESS_MASK); + + if (isAddr) + { + if (fieldHnd == nullptr) + { + // change &X into just plain X + tree->ReplaceWith(lclVarTree, this); + tree->gtType = TYP_BYREF; + } + else + { + // change &(X.f) [i.e. GT_ADDR of local for promoted arg field] + // into &(X, f) [i.e. GT_ADDR of GT_FIELD off ptr param] + lclVarTree->AsLclVarCommon()->SetLclNum(lclNum); + lclVarTree->gtType = TYP_BYREF; + tree->AsOp()->gtOp1 = gtNewFieldRef(fieldRefType, fieldHnd, lclVarTree, fieldOffset); + } + +#ifdef DEBUG + if (verbose) + { + printf("Replacing address of implicit by ref struct parameter with byref:\n"); + } +#endif // DEBUG + } + else + { + // Change X into OBJ(X) or FIELD(X, f) + var_types structType = tree->gtType; + tree->gtType = TYP_BYREF; + + if (fieldHnd) + { + tree->AsLclVarCommon()->SetLclNum(lclNum); + tree = gtNewFieldRef(fieldRefType, fieldHnd, tree, fieldOffset); + } + else + { + tree = gtNewObjNode(lclVarDsc->GetStructHnd(), tree); + + if (structType == TYP_STRUCT) + { + gtSetObjGcInfo(tree->AsObj()); + } + } + + // TODO-CQ: If the VM ever stops violating the ABI and passing heap references + // we could apply TGT_NOT_HEAP here. + tree->gtFlags = (tree->gtFlags & GTF_COMMON_MASK); + +#ifdef DEBUG + if (verbose) + { + printf("Replacing value of implicit by ref struct parameter with indir of parameter:\n"); + } +#endif // DEBUG + } + +#ifdef DEBUG + if (verbose) + { + gtDispTree(tree); + } +#endif // DEBUG + + return tree; } //------------------------------------------------------------------------ diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index 7b6347e9628ee..af04a6b11fcc3 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -385,13 +385,13 @@ unsigned Compiler::optValnumCSE_Index(GenTree* tree, Statement* stmt) bool isSharedConst = false; int configValue = JitConfig.JitConstCSE(); -#if defined(TARGET_ARMARCH) - // ARMARCH - allow to combine with nearby offsets, when config is not 2 or 4 - if ((configValue != CONST_CSE_ENABLE_ARM_NO_SHARING) && (configValue != CONST_CSE_ENABLE_ALL_NO_SHARING)) +#if defined(TARGET_ARM64) + // ARM64 - allow to combine with nearby offsets, when config is not 2 or 4 + if ((configValue != CONST_CSE_ENABLE_ARM64_NO_SHARING) && (configValue != CONST_CSE_ENABLE_ALL_NO_SHARING)) { enableSharedConstCSE = true; } -#endif // TARGET_ARMARCH +#endif // TARGET_ARM64 // All Platforms - also allow to combine with nearby offsets, when config is 3 if (configValue == CONST_CSE_ENABLE_ALL) @@ -785,12 +785,10 @@ bool Compiler::optValnumCSE_Locate() } // Don't allow CSE of constants if it is disabled + // if (tree->IsIntegralConst()) { - if (!enableConstCSE && - // Unconditionally allow these constant handles to be CSE'd - !tree->IsIconHandle(GTF_ICON_STATIC_HDL) && !tree->IsIconHandle(GTF_ICON_CLASS_HDL) && - !tree->IsIconHandle(GTF_ICON_STR_HDL)) + if (!enableConstCSE) { continue; } @@ -2962,9 +2960,9 @@ class CSE_Heuristic do { /* Process the next node in the list */ - GenTree* const exp = lst->tslTree; - Statement* const stmt = lst->tslStmt; - BasicBlock* const blk = lst->tslBlock; + GenTree* exp = lst->tslTree; + Statement* stmt = lst->tslStmt; + BasicBlock* blk = lst->tslBlock; /* Advance to the next node in the list */ lst = lst->tslNext; @@ -3212,9 +3210,9 @@ class CSE_Heuristic noway_assert(asg->AsOp()->gtOp2 == val); } - // Assign the proper Value Numbers. - asg->gtVNPair = ValueNumStore::VNPForVoid(); // The GT_ASG node itself is $VN.Void. - asg->AsOp()->gtOp1->gtVNPair = ValueNumStore::VNPForVoid(); // As is the LHS. + // assign the proper Value Numbers + asg->gtVNPair.SetBoth(ValueNumStore::VNForVoid()); // The GT_ASG node itself is $VN.Void + asg->AsOp()->gtOp1->gtVNPair = val->gtVNPair; // The dest op is the same as 'val' noway_assert(asg->AsOp()->gtOp1->gtOper == GT_LCL_VAR); @@ -3263,7 +3261,7 @@ class CSE_Heuristic cseUse->SetDoNotCSE(); } } - cseUse->gtVNPair = exp->gtVNPair; // The 'cseUse' is equal to the original expression. + cseUse->gtVNPair = val->gtVNPair; // The 'cseUse' is equal to 'val' /* Create a comma node for the CSE assignment */ cse = m_pCompiler->gtNewOperNode(GT_COMMA, expTyp, origAsg, cseUse); @@ -3584,6 +3582,7 @@ bool Compiler::optIsCSEcandidate(GenTree* tree) case GT_ARR_ELEM: case GT_ARR_LENGTH: + case GT_LCL_FLD: return true; case GT_LCL_VAR: @@ -3686,9 +3685,7 @@ bool Compiler::optIsCSEcandidate(GenTree* tree) return true; // allow Intrinsics to be CSE-ed case GT_OBJ: - case GT_LCL_FLD: - // TODO-1stClassStructs: support CSE for enregisterable TYP_STRUCTs. - return varTypeIsEnregisterable(type); + return varTypeIsEnregisterable(type); // Allow enregisterable GT_OBJ's to be CSE-ed. (i.e. SIMD types) case GT_COMMA: return true; // Allow GT_COMMA nodes to be CSE-ed. diff --git a/src/coreclr/jit/optimizer.cpp b/src/coreclr/jit/optimizer.cpp index 315b19caf7ddf..b848d6400bca8 100644 --- a/src/coreclr/jit/optimizer.cpp +++ b/src/coreclr/jit/optimizer.cpp @@ -1725,13 +1725,9 @@ class LoopSearch // Thus, we have to be very careful and after entry discovery check that it is indeed // the only place we enter the loop (especially for non-reducible flow graphs). - JITDUMP("FindLoop: checking head:" FMT_BB " top:" FMT_BB " bottom:" FMT_BB "\n", head->bbNum, top->bbNum, - bottom->bbNum); - if (top->bbNum > bottom->bbNum) // is this a backward edge? (from BOTTOM to TOP) { // Edge from BOTTOM to TOP is not a backward edge - JITDUMP(" " FMT_BB "->" FMT_BB " is not a backedge\n", bottom->bbNum, top->bbNum); return false; } @@ -1739,13 +1735,11 @@ class LoopSearch { // Not a true back-edge; bottom is a block added to reconnect fall-through during // loop processing, so its block number does not reflect its position. - JITDUMP(" " FMT_BB "->" FMT_BB " is not a true backedge\n", bottom->bbNum, top->bbNum); return false; } if (bottom->KindIs(BBJ_EHFINALLYRET, BBJ_EHFILTERRET, BBJ_EHCATCHRET, BBJ_CALLFINALLY, BBJ_SWITCH)) { - JITDUMP(" bottom odd jump kind\n"); // BBJ_EHFINALLYRET, BBJ_EHFILTERRET, BBJ_EHCATCHRET, and BBJ_CALLFINALLY can never form a loop. // BBJ_SWITCH that has a backward jump appears only for labeled break. return false; @@ -1765,7 +1759,6 @@ class LoopSearch if (entry == nullptr) { // For now, we only recognize loops where HEAD has some successor ENTRY in the loop. - JITDUMP(" can't find entry\n"); return false; } @@ -1780,14 +1773,12 @@ class LoopSearch if (!HasSingleEntryCycle()) { // There isn't actually a loop between TOP and BOTTOM - JITDUMP(" not single entry cycle\n"); return false; } if (!loopBlocks.IsMember(top->bbNum)) { // The "back-edge" we identified isn't actually part of the flow cycle containing ENTRY - JITDUMP(" top not in loop\n"); return false; } @@ -1837,7 +1828,6 @@ class LoopSearch if (!MakeCompactAndFindExits()) { // Unable to preserve well-formed loop during compaction. - JITDUMP(" can't compact\n"); return false; } @@ -1938,7 +1928,6 @@ class LoopSearch } else if (!comp->fgDominate(entry, block)) { - JITDUMP(" (find cycle) entry:" FMT_BB " does not dominate " FMT_BB "\n", entry->bbNum, block->bbNum); return false; } @@ -1971,8 +1960,6 @@ class LoopSearch } // There are multiple entries to this loop, don't consider it. - - JITDUMP(" (find cycle) multiple entry:" FMT_BB "\n", block->bbNum); return false; } @@ -1980,7 +1967,6 @@ class LoopSearch if (predBlock == entry) { // We have indeed found a cycle in the flow graph. - JITDUMP(" (find cycle) found cycle\n"); isFirstVisit = !foundCycle; foundCycle = true; assert(loopBlocks.IsMember(predBlock->bbNum)); @@ -2678,9 +2664,6 @@ void Compiler::optFindNaturalLoops() // Make sure that loops are canonical: that every loop has a unique "top", by creating an empty "nop" // one, if necessary, for loops containing others that share a "top." - // - // Also make sure that no loop's "bottom" is another loop's "head". - // for (unsigned char loopInd = 0; loopInd < optLoopCount; loopInd++) { // Traverse the outermost loops as entries into the loop nest; so skip non-outermost. @@ -2891,229 +2874,49 @@ bool Compiler::optIsLoopEntry(BasicBlock* block) const return false; } -//----------------------------------------------------------------------------- -// optCanonicalizeLoopNest: Canonicalize a loop nest -// -// Arguments: -// loopInd - index of outermost loop in the nest -// -// Returns: -// true if the flow graph was modified -// -// Notes: -// For loopInd and all contained loops, ensures each loop top's back edges -// only come from this loop. -// -// Will split top blocks and redirect edges if needed. -// +// Canonicalize the loop nest rooted at parent loop 'loopInd'. +// Returns 'true' if the flow graph is modified. bool Compiler::optCanonicalizeLoopNest(unsigned char loopInd) { - // First canonicalize the loop. - // - bool modified = optCanonicalizeLoop(loopInd); + bool modified = false; + + // Is the top of the current loop in any nested loop? + if (optLoopTable[loopInd].lpTop->bbNatLoopNum != loopInd) + { + if (optCanonicalizeLoop(loopInd)) + { + modified = true; + } + } - // Then any children. - // for (unsigned char child = optLoopTable[loopInd].lpChild; // child != BasicBlock::NOT_IN_LOOP; // child = optLoopTable[child].lpSibling) { - modified |= optCanonicalizeLoopNest(child); + if (optCanonicalizeLoopNest(child)) + { + modified = true; + } } return modified; } -//----------------------------------------------------------------------------- -// optCanonicalizeLoop: ensure that each loop top's back edges come only from -// blocks in the same loop, and that no loop head/bottom blocks coincide. -// -// Arguments: -// loopInd - index of the loop to consider -// -// Returns: -// true if flow changes were made -// -// Notes: -// -// Back edges incident on loop top fall into one three groups: -// -// (1) Outer non-loop backedges (preds dominated by entry where pred is not in loop) -// (2) The canonical backedge (pred == bottom) -// (3) Nested loop backedges or nested non-loop backedges -// (preds dominated by entry, where pred is in loop, pred != bottom) -// -// We assume dominance has already been established by loop recognition (that is, -// anything classified as a loop will have all backedges dominated by loop entry, -// so the only possible non-backedge predecessor of top will be head). -// -// We cannot check dominance here as the flow graph is being modified. -// -// If either set (1) or (3) is non-empty the loop is not canonical. -// -// This method will split the loop top into two or three blocks depending on -// whether (1) or (3) is non-empty, and redirect the edges accordingly. -// -// Loops are canoncalized outer to inner, so inner loops should never see outer loop -// non-backedges, as the parent loop canonicalization should have handled them. -// bool Compiler::optCanonicalizeLoop(unsigned char loopInd) { - bool modified = false; - BasicBlock* const b = optLoopTable[loopInd].lpBottom; - BasicBlock* const t = optLoopTable[loopInd].lpTop; - BasicBlock* const h = optLoopTable[loopInd].lpHead; - BasicBlock* const e = optLoopTable[loopInd].lpEntry; - - // Look for case (1) - // - bool doOuterCanon = false; - - for (BasicBlock* const topPredBlock : t->PredBlocks()) - { - const bool predIsInLoop = (t->bbNum <= topPredBlock->bbNum) && (topPredBlock->bbNum <= b->bbNum); - if (predIsInLoop || (topPredBlock == h)) - { - // no action needed - } - else - { - JITDUMP("in optCanonicalizeLoop: " FMT_LP " top " FMT_BB " (entry " FMT_BB " bottom " FMT_BB - ") %shas a non-loop backedge from " FMT_BB "%s\n", - loopInd, t->bbNum, e->bbNum, b->bbNum, doOuterCanon ? "also " : "", topPredBlock->bbNum, - doOuterCanon ? "" : ": need to canonicalize non-loop backedges"); - doOuterCanon = true; - } - } + // Is the top uniquely part of the current loop? + BasicBlock* t = optLoopTable[loopInd].lpTop; - if (doOuterCanon) + if (t->bbNatLoopNum == loopInd) { - const bool didCanon = optCanonicalizeLoopCore(loopInd, LoopCanonicalizationOption::Outer); - assert(didCanon); - modified |= didCanon; - } - - // Look for case (3) - // - // Outer canon should not update loop top. - // - assert(t == optLoopTable[loopInd].lpTop); - if (t->bbNatLoopNum != loopInd) - { - JITDUMP("in optCanonicalizeLoop: " FMT_LP " has top " FMT_BB " (entry " FMT_BB " bottom " FMT_BB - ") with natural loop number " FMT_LP ": need to canonicalize nested inner loop backedges\n", - loopInd, t->bbNum, e->bbNum, b->bbNum, t->bbNatLoopNum); - - const bool didCanon = optCanonicalizeLoopCore(loopInd, LoopCanonicalizationOption::Current); - assert(didCanon); - modified |= didCanon; - } - - // Check if this loopInd head is also the bottom of some sibling. - // If so, add a block in between to serve as the new head. - // - auto repairLoop = [this](unsigned char loopInd, unsigned char sibling) { - - BasicBlock* const h = optLoopTable[loopInd].lpHead; - BasicBlock* const siblingB = optLoopTable[sibling].lpBottom; - - if (h == siblingB) - { - // We have - // - // sibling.B (== loopInd.H) -e-> loopInd.T - // - // where e is a "critical edge", that is - // * sibling.B has other successors (notably sibling.T), - // * loopInd.T has other predecessors (notably loopInd.B) - // - // turn this into - // - // sibling.B -> newH (== loopInd.H) -> loopInd.T - // - // Ideally we'd just call fgSplitEdge, but we are - // not keeping pred lists in good shape. - // - BasicBlock* const t = optLoopTable[loopInd].lpTop; - assert(siblingB->bbJumpKind == BBJ_COND); - assert(siblingB->bbNext == t); - - JITDUMP(FMT_LP " head " FMT_BB " is also " FMT_LP " bottom\n", loopInd, h->bbNum, sibling); - - BasicBlock* const newH = fgNewBBbefore(BBJ_NONE, t, /*extendRegion*/ true); - - // Anything that flows into sibling will flow here. - // So we use sibling.H as our best guess for weight. - // - newH->inheritWeight(optLoopTable[sibling].lpHead); - newH->bbNatLoopNum = optLoopTable[loopInd].lpParent; - optUpdateLoopHead(loopInd, h, newH); - - return true; - } return false; - }; - - if (optLoopTable[loopInd].lpParent == BasicBlock::NOT_IN_LOOP) - { - // check against all other top-level loops - // - for (unsigned char sibling = 0; sibling < optLoopCount; sibling++) - { - if (optLoopTable[sibling].lpParent != BasicBlock::NOT_IN_LOOP) - { - continue; - } - - modified |= repairLoop(loopInd, sibling); - } - } - else - { - // check against all other sibling loops - // - const unsigned char parentLoop = optLoopTable[loopInd].lpParent; - - for (unsigned char sibling = optLoopTable[parentLoop].lpChild; // - sibling != BasicBlock::NOT_IN_LOOP; // - sibling = optLoopTable[sibling].lpSibling) - { - if (sibling == loopInd) - { - continue; - } - - modified |= repairLoop(loopInd, sibling); - } - } - - if (modified) - { - JITDUMP("Done canonicalizing " FMT_LP "\n\n", loopInd); } - return modified; -} + JITDUMP("in optCanonicalizeLoop: " FMT_LP " has top " FMT_BB " (bottom " FMT_BB ") with natural loop number " FMT_LP + ": need to canonicalize\n", + loopInd, t->bbNum, optLoopTable[loopInd].lpBottom->bbNum, t->bbNatLoopNum); -//----------------------------------------------------------------------------- -// optCanonicalizeLoopCore: ensure that each loop top's back edges come do not -// come from outer/inner loops. -// -// Arguments: -// loopInd - index of the loop to consider -// option - which set of edges to move when canonicalizing -// -// Returns: -// true if flow changes were made -// -// Notes: -// option ::Outer retargets all backedges that do not come from loops in the block. -// option ::Current retargets the canonical backedge (from bottom) -// -bool Compiler::optCanonicalizeLoopCore(unsigned char loopInd, LoopCanonicalizationOption option) -{ - // Otherwise, the top of this loop is also part of a nested loop or has - // non-loop backedges. + // Otherwise, the top of this loop is also part of a nested loop. // // Insert a new unique top for this loop. We must be careful to put this new // block in the correct EH region. Note that t->bbPrev might be in a different @@ -3189,41 +2992,17 @@ bool Compiler::optCanonicalizeLoopCore(unsigned char loopInd, LoopCanonicalizati // want to copy the EH region of the back edge, since that would create a block // outside of and disjoint with the "try" region of the back edge. However, to // simplify things, we disqualify this type of loop, so we should never see this here. - // - BasicBlock* const b = optLoopTable[loopInd].lpBottom; - BasicBlock* const t = optLoopTable[loopInd].lpTop; - BasicBlock* const h = optLoopTable[loopInd].lpHead; + + BasicBlock* h = optLoopTable[loopInd].lpHead; + BasicBlock* b = optLoopTable[loopInd].lpBottom; // The loop must be entirely contained within a single handler region. assert(BasicBlock::sameHndRegion(t, b)); - // We expect h to be already "canonical" -- that is, it falls through to t - // and is not a degenerate BBJ_COND (both branches and falls through to t) - // or a side entry to the loop. - // - // Because of this, introducing a block before t automatically gives us - // the right flow out of h. - // - assert(h->bbNext == t); - assert(h->bbFallsThrough()); - assert((h->bbJumpKind == BBJ_NONE) || (h->bbJumpKind == BBJ_COND)); - if (h->bbJumpKind == BBJ_COND) - { - BasicBlock* const hj = h->bbJumpDest; - assert((hj->bbNum < t->bbNum) || (hj->bbNum > b->bbNum)); - } - // If the bottom block is in the same "try" region, then we extend the EH // region. Otherwise, we add the new block outside the "try" region. - // - const bool extendRegion = BasicBlock::sameTryRegion(t, b); - BasicBlock* const newT = fgNewBBbefore(BBJ_NONE, t, extendRegion); - - // Initially give newT the same weight as t; we will subtract from - // this for each edge that does not move from t to newT. - // - newT->inheritWeight(t); - + const bool extendRegion = BasicBlock::sameTryRegion(t, b); + BasicBlock* newT = fgNewBBbefore(BBJ_NONE, t, extendRegion); if (!extendRegion) { // We need to set the EH region manually. Set it to be the same @@ -3231,154 +3010,112 @@ bool Compiler::optCanonicalizeLoopCore(unsigned char loopInd, LoopCanonicalizati newT->copyEHRegion(b); } - // NewT will be the target for the outer/current loop's backedge(s). - // - BlockToBlockMap* const blockMap = new (getAllocator(CMK_LoopOpt)) BlockToBlockMap(getAllocator(CMK_LoopOpt)); - blockMap->Set(t, newT); - // The new block can reach the same set of blocks as the old one, but don't try to reflect // that in its reachability set here -- creating the new block may have changed the BlockSet // representation from short to long, and canonicalizing loops is immediately followed by // a call to fgUpdateChangedFlowGraph which will recompute the reachability sets anyway. + // Redirect the "bottom" of the current loop to "newT". + BlockToBlockMap* blockMap = new (getAllocator(CMK_LoopOpt)) BlockToBlockMap(getAllocator(CMK_LoopOpt)); + blockMap->Set(t, newT); + optRedirectBlock(b, blockMap); + + // Redirect non-loop preds of "t" to also go to "newT". Inner loops that also branch to "t" should continue + // to do so. However, there maybe be other predecessors from outside the loop nest that need to be updated + // to point to "newT". This normally wouldn't happen, since they too would be part of the loop nest. However, + // they might have been prevented from participating in the loop nest due to different EH nesting, or some + // other reason. + // + // Note that optRedirectBlock doesn't update the predecessors list. So, if the same 't' block is processed + // multiple times while canonicalizing multiple loop nests, we'll attempt to redirect a predecessor multiple times. + // This is ok, because after the first redirection, the topPredBlock branch target will no longer match the source + // edge of the blockMap, so nothing will happen. bool firstPred = true; for (BasicBlock* const topPredBlock : t->PredBlocks()) { - // We set profile weight of newT assuming all edges would - // be redirected there. So, if we don't redirect this edge, - // this is how much we'll have to adjust newT's weight. - // - weight_t weightAdjust = BB_ZERO_WEIGHT; - - if (option == LoopCanonicalizationOption::Current) + // Skip if topPredBlock is in the loop. + // Note that this uses block number to detect membership in the loop. We are adding blocks during + // canonicalization, and those block numbers will be new, and larger than previous blocks. However, we work + // outside-in, so we shouldn't encounter the new blocks at the loop boundaries, or in the predecessor lists. + if (t->bbNum <= topPredBlock->bbNum && topPredBlock->bbNum <= b->bbNum) { - // Redirect the (one and only) true backedge of this loop. - // - if (topPredBlock != b) - { - if ((topPredBlock != h) && topPredBlock->hasProfileWeight()) - { - // Note this may overstate the adjustment, if topPredBlock is BBJ_COND. - // - weightAdjust = topPredBlock->bbWeight; - } - } - else - { - JITDUMP("in optCanonicalizeLoop (current): redirect bottom->top backedge " FMT_BB " -> " FMT_BB - " to " FMT_BB " -> " FMT_BB "\n", - topPredBlock->bbNum, t->bbNum, topPredBlock->bbNum, newT->bbNum); - optRedirectBlock(b, blockMap); - } + JITDUMP("in optCanonicalizeLoop: 'top' predecessor " FMT_BB " is in the range of " FMT_LP " (" FMT_BB + ".." FMT_BB "); not redirecting its bottom edge\n", + topPredBlock->bbNum, loopInd, t->bbNum, b->bbNum); + continue; } - else if (option == LoopCanonicalizationOption::Outer) + + JITDUMP("in optCanonicalizeLoop: redirect top predecessor " FMT_BB " to " FMT_BB "\n", topPredBlock->bbNum, + newT->bbNum); + optRedirectBlock(topPredBlock, blockMap); + + // When we have profile data then the 'newT' block will inherit topPredBlock profile weight + if (topPredBlock->hasProfileWeight()) { - // Redirect non-loop preds of "t" to go to "newT". Inner loops that also branch to "t" should continue - // to do so. However, there maybe be other predecessors from outside the loop nest that need to be updated - // to point to "newT". This normally wouldn't happen, since they too would be part of the loop nest. - // However, - // they might have been prevented from participating in the loop nest due to different EH nesting, or some - // other reason. - // - // Skip if topPredBlock is in the loop. - // Note that this uses block number to detect membership in the loop. We are adding blocks during - // canonicalization, and those block numbers will be new, and larger than previous blocks. However, we work - // outside-in, so we shouldn't encounter the new blocks at the loop boundaries, or in the predecessor lists. + // This corrects an issue when the topPredBlock has a profile based weight // - if ((t->bbNum <= topPredBlock->bbNum) && (topPredBlock->bbNum <= b->bbNum)) + if (firstPred) { - if (topPredBlock->hasProfileWeight()) - { - // Note this may overstate the adjustment, if topPredBlock is BBJ_COND. - // - weightAdjust = topPredBlock->bbWeight; - } + JITDUMP("in optCanonicalizeLoop: block " FMT_BB " will inheritWeight from " FMT_BB "\n", newT->bbNum, + topPredBlock->bbNum); + + newT->inheritWeight(topPredBlock); + firstPred = false; } else { - JITDUMP("in optCanonicalizeLoop (outer): redirect %s->top %sedge " FMT_BB " -> " FMT_BB " to " FMT_BB - " -> " FMT_BB "\n", - topPredBlock == h ? "head" : "nonloop", topPredBlock == h ? "" : "back", topPredBlock->bbNum, - t->bbNum, topPredBlock->bbNum, newT->bbNum); - optRedirectBlock(topPredBlock, blockMap); - } - } - else - { - unreached(); - } - - if (weightAdjust > BB_ZERO_WEIGHT) - { - JITDUMP("in optCanonicalizeLoop: removing block " FMT_BB " weight " FMT_WT " from " FMT_BB "\n", - topPredBlock->bbNum, weightAdjust, newT->bbNum); + JITDUMP("in optCanonicalizeLoop: block " FMT_BB " will also contribute to the weight of " FMT_BB "\n", + newT->bbNum, topPredBlock->bbNum); - if (newT->bbWeight >= weightAdjust) - { - newT->setBBProfileWeight(newT->bbWeight - weightAdjust); - } - else if (newT->bbWeight > BB_ZERO_WEIGHT) - { - newT->setBBProfileWeight(BB_ZERO_WEIGHT); + weight_t newWeight = newT->getBBWeight(this) + topPredBlock->getBBWeight(this); + newT->setBBProfileWeight(newWeight); } } } - assert(h->bbNext == newT); assert(newT->bbNext == t); - // With the Option::Current we are changing which block is loop top. - // Make suitable updates. - // - if (option == LoopCanonicalizationOption::Current) + // If it had been a do-while loop (top == entry), update entry, as well. + BasicBlock* origE = optLoopTable[loopInd].lpEntry; + if (optLoopTable[loopInd].lpTop == origE) { - JITDUMP("in optCanonicalizeLoop (current): " FMT_BB " is now the top of loop " FMT_LP "\n", newT->bbNum, - loopInd); - - optLoopTable[loopInd].lpTop = newT; - newT->bbNatLoopNum = loopInd; + optLoopTable[loopInd].lpEntry = newT; + } + optLoopTable[loopInd].lpTop = newT; - // If loopInd was a do-while loop (top == entry), update entry, as well. - // - BasicBlock* const origE = optLoopTable[loopInd].lpEntry; - if (origE == t) - { - JITDUMP("updating entry of " FMT_LP " to " FMT_BB "\n", loopInd, newT->bbNum); - optLoopTable[loopInd].lpEntry = newT; - } + newT->bbNatLoopNum = loopInd; - // If any loops nested in "loopInd" have the same head and entry as "loopInd", - // it must be the case that they were do-while's (since "h" fell through to the entry). - // The new node "newT" becomes the head of such loops. - for (unsigned char childLoop = optLoopTable[loopInd].lpChild; // - childLoop != BasicBlock::NOT_IN_LOOP; // - childLoop = optLoopTable[childLoop].lpSibling) - { - if ((optLoopTable[childLoop].lpEntry == origE) && (optLoopTable[childLoop].lpHead == h) && - (newT->bbJumpKind == BBJ_NONE) && (newT->bbNext == origE)) - { - optUpdateLoopHead(childLoop, h, newT); + JITDUMP("in optCanonicalizeLoop: made new block " FMT_BB " [%p] the new unique top of loop %d.\n", newT->bbNum, + dspPtr(newT), loopInd); - // Fix pred list here, so when we walk preds of child loop tops - // we see the right blocks. - // - fgReplacePred(optLoopTable[childLoop].lpTop, h, newT); - } - } + // Make sure the head block still goes to the entry... + if (h->bbJumpKind == BBJ_NONE && h->bbNext != optLoopTable[loopInd].lpEntry) + { + h->bbJumpKind = BBJ_ALWAYS; + h->bbJumpDest = optLoopTable[loopInd].lpEntry; } - else if (option == LoopCanonicalizationOption::Outer) + else if (h->bbJumpKind == BBJ_COND && h->bbNext == newT && newT != optLoopTable[loopInd].lpEntry) { - JITDUMP("in optCanonicalizeLoop (outer): " FMT_BB " is outside of loop " FMT_LP "\n", newT->bbNum, loopInd); - - // If we are lifting outer backeges, then newT belongs to our parent loop - // - newT->bbNatLoopNum = optLoopTable[loopInd].lpParent; - - // newT is now the header of this loop - // - optUpdateLoopHead(loopInd, h, newT); + BasicBlock* h2 = fgNewBBafter(BBJ_ALWAYS, h, /*extendRegion*/ true); + optLoopTable[loopInd].lpHead = h2; + h2->bbJumpDest = optLoopTable[loopInd].lpEntry; + h2->bbStmtList = nullptr; + fgInsertStmtAtEnd(h2, fgNewStmtFromTree(gtNewOperNode(GT_NOP, TYP_VOID, nullptr))); } + // If any loops nested in "loopInd" have the same head and entry as "loopInd", + // it must be the case that they were do-while's (since "h" fell through to the entry). + // The new node "newT" becomes the head of such loops. + for (unsigned char childLoop = optLoopTable[loopInd].lpChild; // + childLoop != BasicBlock::NOT_IN_LOOP; // + childLoop = optLoopTable[childLoop].lpSibling) + { + if (optLoopTable[childLoop].lpEntry == origE && optLoopTable[childLoop].lpHead == h && + newT->bbJumpKind == BBJ_NONE && newT->bbNext == origE) + { + optUpdateLoopHead(childLoop, h, newT); + } + } return true; } @@ -3414,22 +3151,6 @@ bool Compiler::optLoopContains(unsigned l1, unsigned l2) const } } -//----------------------------------------------------------------------------- -// optLoopEntry: For a given preheader of a loop, returns the lpEntry. -// -// Arguments: -// preHeader -- preheader of a loop -// -// Returns: -// Corresponding loop entry block. -// -BasicBlock* Compiler::optLoopEntry(BasicBlock* preHeader) -{ - assert((preHeader->bbFlags & BBF_LOOP_PREHEADER) != 0); - - return (preHeader->bbJumpDest == nullptr) ? preHeader->bbNext : preHeader->bbJumpDest; -} - //----------------------------------------------------------------------------- // optUpdateLoopHead: Replace the `head` block of a loop in the loop table. // Considers all child loops that might share the same head (recursively). @@ -6271,7 +5992,6 @@ void Compiler::optPerformHoistExpr(GenTree* origExpr, BasicBlock* exprBb, unsign { printf("\nHoisting a copy of "); printTreeID(origExpr); - printf(" " FMT_VN, origExpr->gtVNPair.GetLiberal()); printf(" from " FMT_BB " into PreHeader " FMT_BB " for loop " FMT_LP " <" FMT_BB ".." FMT_BB ">:\n", exprBb->bbNum, optLoopTable[lnum].lpHead->bbNum, lnum, optLoopTable[lnum].lpTop->bbNum, optLoopTable[lnum].lpBottom->bbNum); @@ -6542,51 +6262,46 @@ void Compiler::optHoistLoopNest(unsigned lnum, LoopHoistContext* hoistCtxt) m_loopsConsidered++; #endif // LOOP_HOIST_STATS - BasicBlockList* preHeadersOfChildLoops = nullptr; - BasicBlockList* firstPreHeader = nullptr; + optHoistThisLoop(lnum, hoistCtxt); + + VNSet* hoistedInCurLoop = hoistCtxt->ExtractHoistedInCurLoop(); if (optLoopTable[lnum].lpChild != BasicBlock::NOT_IN_LOOP) { - BitVecTraits m_visitedTraits(fgBBNumMax * 2, this); - BitVec m_visited(BitVecOps::MakeEmpty(&m_visitedTraits)); + // Add the ones hoisted in "lnum" to "hoistedInParents" for any nested loops. + // TODO-Cleanup: we should have a set abstraction for loops. + if (hoistedInCurLoop != nullptr) + { + for (VNSet::KeyIterator keys = hoistedInCurLoop->Begin(); !keys.Equal(hoistedInCurLoop->End()); ++keys) + { +#ifdef DEBUG + bool b; + assert(!hoistCtxt->m_hoistedInParentLoops.Lookup(keys.Get(), &b)); +#endif + hoistCtxt->m_hoistedInParentLoops.Set(keys.Get(), true); + } + } for (unsigned child = optLoopTable[lnum].lpChild; child != BasicBlock::NOT_IN_LOOP; child = optLoopTable[child].lpSibling) { optHoistLoopNest(child, hoistCtxt); + } - if (optLoopTable[child].lpFlags & LPFLG_HAS_PREHEAD) + // Now remove them. + // TODO-Cleanup: we should have a set abstraction for loops. + if (hoistedInCurLoop != nullptr) + { + for (VNSet::KeyIterator keys = hoistedInCurLoop->Begin(); !keys.Equal(hoistedInCurLoop->End()); ++keys) { - // If any preheaders were found, add them to the tracking list - - BasicBlock* preHeaderBlock = optLoopTable[child].lpHead; - if (!BitVecOps::IsMember(&m_visitedTraits, m_visited, preHeaderBlock->bbNum)) - { - BitVecOps::AddElemD(&m_visitedTraits, m_visited, preHeaderBlock->bbNum); - JITDUMP(" PREHEADER: " FMT_BB "\n", preHeaderBlock->bbNum); - - // Here, we are arranging the blocks in reverse execution order, so when they are pushed - // on the stack that hoist these blocks further sees them in execution order. - if (firstPreHeader == nullptr) - { - preHeadersOfChildLoops = new (this, CMK_LoopHoist) BasicBlockList(preHeaderBlock, nullptr); - firstPreHeader = preHeadersOfChildLoops; - } - else - { - preHeadersOfChildLoops->next = - new (this, CMK_LoopHoist) BasicBlockList(preHeaderBlock, nullptr); - preHeadersOfChildLoops = preHeadersOfChildLoops->next; - } - } + // Note that we asserted when we added these that they hadn't been members, so removing is appropriate. + hoistCtxt->m_hoistedInParentLoops.Remove(keys.Get()); } } } - - optHoistThisLoop(lnum, hoistCtxt, firstPreHeader); } -void Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt, BasicBlockList* existingPreHeaders) +void Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt) { LoopDsc* pLoopDsc = &optLoopTable[lnum]; @@ -6698,61 +6413,24 @@ void Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt, Basi // or side-effect dependent things. // // We really should consider hoisting from conditionally executed blocks, if they are frequently executed - // and it is safe to evaluate the tree early + // and it is safe to evaluate the tree early. + // + // In particular if we have a loop nest, when scanning the outer loop we should consider hoisting from blocks + // in enclosed loops. However, this is likely to scale poorly, and we really should instead start + // hoisting inner to outer. // ArrayStack defExec(getAllocatorLoopHoist()); - - bool pushAllPreheaders = false; - if (pLoopDsc->lpExitCnt == 1) { assert(pLoopDsc->lpExit != nullptr); - JITDUMP(" Considering hoisting in blocks that either dominate exit block " FMT_BB - " or preheaders of nested loops, if any:\n", - pLoopDsc->lpExit->bbNum); - + JITDUMP(" Only considering hoisting in blocks that dominate exit block " FMT_BB "\n", pLoopDsc->lpExit->bbNum); + BasicBlock* cur = pLoopDsc->lpExit; // Push dominators, until we reach "entry" or exit the loop. - // Also push the preheaders that were added for the nested loops, - // if any, along the way such that in the final list, the dominating - // blocks are visited before the dominated blocks. - // - // TODO-CQ: In future, we should create preheaders upfront before building - // dominators so we don't have to do this extra work here. - BasicBlock* cur = pLoopDsc->lpExit; - BasicBlockList* preHeadersList = existingPreHeaders; - while (cur != nullptr && pLoopDsc->lpContains(cur) && cur != pLoopDsc->lpEntry) { - JITDUMP(" -- " FMT_BB " (dominate exit block)\n", cur->bbNum); defExec.Push(cur); cur = cur->bbIDom; - - if (preHeadersList != nullptr) - { - BasicBlock* preHeaderBlock = preHeadersList->block; - BasicBlock* lpEntry = optLoopEntry(preHeaderBlock); - if (cur->bbNum < lpEntry->bbNum) - { - JITDUMP(" -- " FMT_BB " (preheader of " FMT_LP ")\n", preHeaderBlock->bbNum, - lpEntry->bbNatLoopNum); - - defExec.Push(preHeaderBlock); - preHeadersList = preHeadersList->next; - } - } - } - - // Push the remaining preheaders, if any. This usually will happen if entry - // and exit blocks of lnum is same. - while (preHeadersList != nullptr) - { - BasicBlock* preHeaderBlock = preHeadersList->block; - JITDUMP(" -- " FMT_BB " (preheader of " FMT_LP ")\n", preHeaderBlock->bbNum, - optLoopEntry(preHeaderBlock)->bbNatLoopNum); - defExec.Push(preHeaderBlock); - preHeadersList = preHeadersList->next; } - // If we didn't reach the entry block, give up and *just* push the entry block. if (cur != pLoopDsc->lpEntry) { @@ -6760,37 +6438,17 @@ void Compiler::optHoistThisLoop(unsigned lnum, LoopHoistContext* hoistCtxt, Basi "block " FMT_BB "\n", pLoopDsc->lpEntry->bbNum); defExec.Reset(); - pushAllPreheaders = true; } + defExec.Push(pLoopDsc->lpEntry); } else // More than one exit { + JITDUMP(" only considering hoisting in entry block " FMT_BB "\n", pLoopDsc->lpEntry->bbNum); // We'll assume that only the entry block is definitely executed. // We could in the future do better. - - JITDUMP(" Considering hoisting in entry block " FMT_BB " because " FMT_LP " has more than one exit\n", - pLoopDsc->lpEntry->bbNum, lnum); - pushAllPreheaders = true; + defExec.Push(pLoopDsc->lpEntry); } - if (pushAllPreheaders) - { - // We will still push all the preheaders found. - BasicBlockList* preHeadersList = existingPreHeaders; - - while (preHeadersList != nullptr) - { - BasicBlock* preHeaderBlock = preHeadersList->block; - JITDUMP(" -- " FMT_BB " (preheader of " FMT_LP ")\n", preHeaderBlock->bbNum, - optLoopEntry(preHeaderBlock)->bbNatLoopNum); - defExec.Push(preHeaderBlock); - preHeadersList = preHeadersList->next; - } - } - - JITDUMP(" -- " FMT_BB " (entry block)\n", pLoopDsc->lpEntry->bbNum); - defExec.Push(pLoopDsc->lpEntry); - optHoistLoopBlocks(lnum, &defExec, hoistCtxt); } @@ -7107,24 +6765,6 @@ void Compiler::optHoistLoopBlocks(unsigned loopNum, ArrayStack* blo return vnIsInvariant; } - bool IsHoistableOverExcepSibling(GenTree* node, bool siblingHasExcep) - { - JITDUMP(" [%06u]", dspTreeID(node)); - - if ((node->gtFlags & GTF_ALL_EFFECT) != 0) - { - // If the hoistable node has any side effects, make sure - // we don't hoist it past a sibling that throws any exception. - if (siblingHasExcep) - { - JITDUMP(" not hoistable: cannot move past node that throws exception.\n"); - return false; - } - } - JITDUMP(" hoistable\n"); - return true; - } - //------------------------------------------------------------------------ // IsTreeLoopMemoryInvariant: determine if the value number of tree // is dependent on the tree being executed within the current loop @@ -7228,7 +6868,6 @@ void Compiler::optHoistLoopBlocks(unsigned loopNum, ArrayStack* blo fgWalkResult PostOrderVisit(GenTree** use, GenTree* user) { GenTree* tree = *use; - JITDUMP("----- PostOrderVisit for [%06u]\n", dspTreeID(tree)); if (tree->OperIsLocal()) { @@ -7535,15 +7174,6 @@ void Compiler::optHoistLoopBlocks(unsigned loopNum, ArrayStack* blo // cctor dependent node is initially not hoistable and may become hoistable later, // when its parent comma node is visited. // - // TODO-CQ: Ideally, we should be hoisting all the nodes having side-effects in execution - // order as well as the ones that don't have side-effects at all. However, currently, we - // just restrict hoisting a node(s) (that are children of `comma`) if one of the siblings - // (which is executed before the given node) has side-effects (exceptions). "Descendants - // of ancestors might have side-effects and we might hoist nodes past them. This needs - // to be addressed properly. - bool visitedCurr = false; - bool isCommaTree = tree->OperIs(GT_COMMA); - bool hasExcep = false; for (int i = 0; i < m_valueStack.Height(); i++) { Value& value = m_valueStack.BottomRef(i); @@ -7552,32 +7182,17 @@ void Compiler::optHoistLoopBlocks(unsigned loopNum, ArrayStack* blo { assert(value.Node() != tree); - if (IsHoistableOverExcepSibling(value.Node(), hasExcep)) - { - m_compiler->optHoistCandidate(value.Node(), m_currentBlock, m_loopNum, m_hoistContext); - } - // Don't hoist this tree again. value.m_hoistable = false; value.m_invariant = false; + + m_compiler->optHoistCandidate(value.Node(), m_currentBlock, m_loopNum, m_hoistContext); } else if (value.Node() != tree) { - if (visitedCurr && isCommaTree) - { - // If we have visited current tree, now we are visiting children. - // For GT_COMMA nodes, we want to track if any children throws and - // should not hoist further children past it. - hasExcep = (tree->gtFlags & GTF_EXCEPT) != 0; - } JITDUMP(" [%06u] not %s: %s\n", dspTreeID(value.Node()), value.m_invariant ? "invariant" : "hoistable", value.m_failReason); } - else - { - visitedCurr = true; - JITDUMP(" [%06u] not hoistable : current node\n", dspTreeID(value.Node())); - } } } @@ -7621,8 +7236,6 @@ void Compiler::optHoistLoopBlocks(unsigned loopNum, ArrayStack* blo visitor.HoistBlock(block); } - - hoistContext->ResetHoistedInCurLoop(); } void Compiler::optHoistCandidate(GenTree* tree, BasicBlock* treeBb, unsigned lnum, LoopHoistContext* hoistCtxt) @@ -7636,12 +7249,17 @@ void Compiler::optHoistCandidate(GenTree* tree, BasicBlock* treeBb, unsigned lnu return; } + if (hoistCtxt->m_hoistedInParentLoops.Lookup(tree->gtVNPair.GetLiberal())) + { + JITDUMP(" ... already hoisted same VN in parent\n"); + // already hoisted in a parent loop, so don't hoist this expression. + return; + } + if (hoistCtxt->GetHoistedInCurLoop(this)->Lookup(tree->gtVNPair.GetLiberal())) { + JITDUMP(" ... already hoisted same VN in current\n"); // already hoisted this expression in the current loop, so don't hoist this expression. - - JITDUMP(" [%06u] ... already hoisted " FMT_VN " in " FMT_LP "\n ", dspTreeID(tree), - tree->gtVNPair.GetLiberal(), lnum); return; } diff --git a/src/coreclr/jit/patchpoint.cpp b/src/coreclr/jit/patchpoint.cpp index bf7560dd431a1..d1478c51c3123 100644 --- a/src/coreclr/jit/patchpoint.cpp +++ b/src/coreclr/jit/patchpoint.cpp @@ -78,7 +78,7 @@ class PatchpointTransformer // If we're instrumenting, we should not have decided to // put class probes here, as that is driven by looking at IL. // - assert((block->bbFlags & BBF_HAS_HISTOGRAM_PROFILE) == 0); + assert((block->bbFlags & BBF_HAS_CLASS_PROFILE) == 0); // Clear the partial comp flag. // diff --git a/src/coreclr/jit/rangecheck.cpp b/src/coreclr/jit/rangecheck.cpp index 6b1575ab5f928..970e799d9b509 100644 --- a/src/coreclr/jit/rangecheck.cpp +++ b/src/coreclr/jit/rangecheck.cpp @@ -947,14 +947,14 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool return range; } // Generalized range computation not implemented for these operators - else if (binop->OperIs(GT_AND, GT_UMOD)) + else if (binop->OperIs(GT_AND, GT_UMOD, GT_RSH)) { return Range(Limit::keUnknown); } } // other operators are expected to be handled above. - assert(binop->OperIs(GT_ADD, GT_MUL, GT_LSH, GT_RSH)); + assert(binop->OperIs(GT_ADD, GT_MUL, GT_LSH)); Range* op1RangeCached = nullptr; Range op1Range = Limit(Limit::keUndef); @@ -1024,43 +1024,9 @@ Range RangeCheck::ComputeRangeForBinOp(BasicBlock* block, GenTreeOp* binop, bool convertedOp2Range.ToString(m_pCompiler->getAllocatorDebugOnly()), r.ToString(m_pCompiler->getAllocatorDebugOnly())); } - else if (binop->OperIs(GT_RSH)) - { - r = RangeOps::ShiftRight(op1Range, op2Range); - JITDUMP("Right shift range: %s >> %s = %s\n", op1Range.ToString(m_pCompiler->getAllocatorDebugOnly()), - op2Range.ToString(m_pCompiler->getAllocatorDebugOnly()), - r.ToString(m_pCompiler->getAllocatorDebugOnly())); - } return r; } -//------------------------------------------------------------------------ -// GetRangeFromType: Compute the range from the given type -// -// Arguments: -// type - input type -// -// Return value: -// range that represents the values given type allows -// -Range RangeCheck::GetRangeFromType(var_types type) -{ - switch (type) - { - case TYP_BOOL: - case TYP_UBYTE: - return Range(Limit(Limit::keConstant, 0), Limit(Limit::keConstant, BYTE_MAX)); - case TYP_BYTE: - return Range(Limit(Limit::keConstant, INT8_MIN), Limit(Limit::keConstant, INT8_MAX)); - case TYP_USHORT: - return Range(Limit(Limit::keConstant, 0), Limit(Limit::keConstant, UINT16_MAX)); - case TYP_SHORT: - return Range(Limit(Limit::keConstant, INT16_MIN), Limit(Limit::keConstant, INT16_MAX)); - default: - return Range(Limit(Limit::keUnknown)); - } -} - // Compute the range for a local var definition. Range RangeCheck::ComputeRangeForLocalDef(BasicBlock* block, GenTreeLclVarCommon* lcl, @@ -1276,11 +1242,11 @@ bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr) { overflows = false; } - else if (expr->OperIs(GT_IND)) + else if (expr->OperGet() == GT_IND) { overflows = false; } - else if (expr->OperIs(GT_COMMA)) + else if (expr->OperGet() == GT_COMMA) { overflows = ComputeDoesOverflow(block, expr->gtEffectiveVal()); } @@ -1290,7 +1256,7 @@ bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr) overflows = DoesVarDefOverflow(expr->AsLclVarCommon()); } // Check if add overflows. - else if (expr->OperIs(GT_ADD, GT_MUL)) + else if (expr->OperGet() == GT_ADD || expr->OperGet() == GT_MUL) { overflows = DoesBinOpOverflow(block, expr->AsOp()); } @@ -1301,14 +1267,10 @@ bool RangeCheck::ComputeDoesOverflow(BasicBlock* block, GenTree* expr) overflows = false; } // Walk through phi arguments to check if phi arguments involve arithmetic that overflows. - else if (expr->OperIs(GT_PHI)) + else if (expr->OperGet() == GT_PHI) { overflows = DoesPhiOverflow(block, expr); } - else if (expr->OperIs(GT_CAST)) - { - overflows = ComputeDoesOverflow(block, expr->gtGetOp1()); - } GetOverflowMap()->Set(expr, overflows, OverflowMap::Overwrite); m_pSearchPath->Remove(expr); JITDUMP("[%06d] %s\n", Compiler::dspTreeID(expr), ((overflows) ? "overflows" : "does not overflow")); @@ -1395,7 +1357,7 @@ Range RangeCheck::ComputeRange(BasicBlock* block, GenTree* expr, bool monIncreas range = ComputeRangeForBinOp(block, expr->AsOp(), monIncreasing DEBUGARG(indent + 1)); } // If phi, then compute the range for arguments, calling the result "dependent" when looping begins. - else if (expr->OperIs(GT_PHI)) + else if (expr->OperGet() == GT_PHI) { for (GenTreePhi::Use& use : expr->AsPhi()->Uses()) { @@ -1420,20 +1382,31 @@ Range RangeCheck::ComputeRange(BasicBlock* block, GenTree* expr, bool monIncreas } else if (varTypeIsSmallInt(expr->TypeGet())) { - range = GetRangeFromType(expr->TypeGet()); + switch (expr->TypeGet()) + { + case TYP_UBYTE: + range = Range(Limit(Limit::keConstant, 0), Limit(Limit::keConstant, 255)); + break; + case TYP_BYTE: + range = Range(Limit(Limit::keConstant, -128), Limit(Limit::keConstant, 127)); + break; + case TYP_USHORT: + range = Range(Limit(Limit::keConstant, 0), Limit(Limit::keConstant, 65535)); + break; + case TYP_SHORT: + range = Range(Limit(Limit::keConstant, -32768), Limit(Limit::keConstant, 32767)); + break; + default: + range = Range(Limit(Limit::keUnknown)); + break; + } + JITDUMP("%s\n", range.ToString(m_pCompiler->getAllocatorDebugOnly())); } - else if (expr->OperIs(GT_COMMA)) + else if (expr->OperGet() == GT_COMMA) { range = GetRange(block, expr->gtEffectiveVal(), monIncreasing DEBUGARG(indent + 1)); } - else if (expr->OperIs(GT_CAST)) - { - GenTreeCast* castTree = expr->AsCast(); - // TODO: consider computing range for CastOp and intersect it - // with this - range = GetRangeFromType(castTree->CastToType()); - } else { // The expression is not recognized, so the result is unknown. diff --git a/src/coreclr/jit/rangecheck.h b/src/coreclr/jit/rangecheck.h index db1c25a09eda5..49c5a2950a939 100644 --- a/src/coreclr/jit/rangecheck.h +++ b/src/coreclr/jit/rangecheck.h @@ -101,27 +101,27 @@ struct Limit assert(type == keBinOpArray); } - bool IsUndef() const + bool IsUndef() { return type == keUndef; } - bool IsDependent() const + bool IsDependent() { return type == keDependent; } - bool IsUnknown() const + bool IsUnknown() { return type == keUnknown; } - bool IsConstant() const + bool IsConstant() { return type == keConstant; } - int GetConstant() const + int GetConstant() { return cns; } - bool IsBinOpArray() const + bool IsBinOpArray() { return type == keBinOpArray; } @@ -170,27 +170,6 @@ struct Limit return false; } - bool ShiftRightConstant(int i) - { - switch (type) - { - case keDependent: - return true; - case keBinOpArray: - case keConstant: - // >> never overflows - assert((unsigned)i <= 31); - cns >>= i; - return true; - case keUndef: - case keUnknown: - // For these values of 'type', conservatively return false - break; - } - - return false; - } - bool Equals(Limit& l) { switch (type) @@ -278,40 +257,34 @@ struct Range // Helpers for operations performed on ranges struct RangeOps { - // Perform 'value' + 'cns' - static Limit AddConstantLimit(const Limit& value, const Limit& cns) + // Given a constant limit in "l1", add it to l2 and mutate "l2". + static Limit AddConstantLimit(Limit& l1, Limit& l2) { - assert(cns.IsConstant()); - Limit l = value; - if (l.AddConstant(cns.GetConstant())) + assert(l1.IsConstant()); + Limit l = l2; + if (l.AddConstant(l1.GetConstant())) { return l; } - return Limit(Limit::keUnknown); + else + { + return Limit(Limit::keUnknown); + } } - // Perform 'value' * 'cns' - static Limit MultiplyConstantLimit(const Limit& value, const Limit& cns) + // Given a constant limit in "l1", multiply it to l2 and mutate "l2". + static Limit MultiplyConstantLimit(Limit& l1, Limit& l2) { - assert(cns.IsConstant()); - Limit l = value; - if (l.MultiplyConstant(cns.GetConstant())) + assert(l1.IsConstant()); + Limit l = l2; + if (l.MultiplyConstant(l1.GetConstant())) { return l; } - return Limit(Limit::keUnknown); - } - - // Perform 'value' >> 'cns' - static Limit ShiftRightConstantLimit(const Limit& value, const Limit& cns) - { - assert(value.IsConstant()); - Limit result = value; - if (result.ShiftRightConstant(cns.GetConstant())) + else { - return result; + return Limit(Limit::keUnknown); } - return Limit(Limit::keUnknown); } // Given two ranges "r1" and "r2", perform an add operation on the @@ -338,57 +311,20 @@ struct RangeOps if (r1lo.IsConstant()) { - result.lLimit = AddConstantLimit(r2lo, r1lo); + result.lLimit = AddConstantLimit(r1lo, r2lo); } if (r2lo.IsConstant()) { - result.lLimit = AddConstantLimit(r1lo, r2lo); + result.lLimit = AddConstantLimit(r2lo, r1lo); } if (r1hi.IsConstant()) - { - result.uLimit = AddConstantLimit(r2hi, r1hi); - } - if (r2hi.IsConstant()) { result.uLimit = AddConstantLimit(r1hi, r2hi); } - return result; - } - - static Range ShiftRight(Range& r1, Range& r2) - { - Limit& r1lo = r1.LowerLimit(); - Limit& r1hi = r1.UpperLimit(); - Limit& r2lo = r2.LowerLimit(); - Limit& r2hi = r2.UpperLimit(); - - Range result = Limit(Limit::keUnknown); - - // For now we only support r1 >> positive_cns (to simplify) - if (!r2lo.IsConstant() || !r2hi.IsConstant() || (r2lo.cns < 0) || (r2hi.cns < 0)) - { - return result; - } - - // Check lo ranges if they are dependent and not unknown. - if (r1lo.IsDependent()) - { - result.lLimit = Limit(Limit::keDependent); - } - else if (r1lo.IsConstant()) - { - result.lLimit = ShiftRightConstantLimit(r1lo, r2lo); - } - - if (r1hi.IsDependent()) - { - result.uLimit = Limit(Limit::keDependent); - } - else if (r1hi.IsConstant()) + if (r2hi.IsConstant()) { - result.uLimit = ShiftRightConstantLimit(r1hi, r2hi); + result.uLimit = AddConstantLimit(r2hi, r1hi); } - return result; } @@ -416,19 +352,19 @@ struct RangeOps if (r1lo.IsConstant()) { - result.lLimit = MultiplyConstantLimit(r2lo, r1lo); + result.lLimit = MultiplyConstantLimit(r1lo, r2lo); } if (r2lo.IsConstant()) { - result.lLimit = MultiplyConstantLimit(r1lo, r2lo); + result.lLimit = MultiplyConstantLimit(r2lo, r1lo); } if (r1hi.IsConstant()) { - result.uLimit = MultiplyConstantLimit(r2hi, r1hi); + result.uLimit = MultiplyConstantLimit(r1hi, r2hi); } if (r2hi.IsConstant()) { - result.uLimit = MultiplyConstantLimit(r1hi, r2hi); + result.uLimit = MultiplyConstantLimit(r2hi, r1hi); } return result; } @@ -624,9 +560,6 @@ class RangeCheck // at phi definitions for the lower bound. Range GetRange(BasicBlock* block, GenTree* expr, bool monIncreasing DEBUGARG(int indent)); - // Compute the range from the given type - Range GetRangeFromType(var_types type); - // Given the local variable, first find the definition of the local and find the range of the rhs. // Helper for GetRange. Range ComputeRangeForLocalDef(BasicBlock* block, GenTreeLclVarCommon* lcl, bool monIncreasing DEBUGARG(int indent)); diff --git a/src/coreclr/jit/rationalize.cpp b/src/coreclr/jit/rationalize.cpp index 4cb2d7261fab9..e6b7e1a4d9234 100644 --- a/src/coreclr/jit/rationalize.cpp +++ b/src/coreclr/jit/rationalize.cpp @@ -134,6 +134,23 @@ void Rationalizer::RewriteSIMDIndir(LIR::Use& use) addr->gtType = simdType; use.ReplaceWith(addr); } + else if (addr->OperIs(GT_ADDR)) + { + GenTree* location = addr->AsUnOp()->gtGetOp1(); + + if (location->OperIsSimdOrHWintrinsic() || location->IsCnsVec()) + { + // If we have IND(ADDR(SIMD)) then we can keep only the SIMD node. + // This is a special tree created by impNormStructVal to preserve the class layout + // needed by call morphing on an OBJ node. This information is no longer needed at + // this point (and the address of a SIMD node can't be obtained anyway). + + BlockRange().Remove(indir); + BlockRange().Remove(addr); + + use.ReplaceWith(addr->AsUnOp()->gtGetOp1()); + } + } #endif // FEATURE_SIMD } @@ -248,62 +265,6 @@ void Rationalizer::RewriteIntrinsicAsUserCall(GenTree** use, ArrayStack a % cns -// where cns is a signed integer constant that is a power of 2. -// We do this transformation because Lowering has a specific optimization -// for 'a % cns' that is not easily reduced by other means. -// -void Rationalizer::RewriteSubLshDiv(GenTree** use) -{ - if (!comp->opts.OptimizationEnabled()) - return; - - GenTree* const node = *use; - - if (!node->OperIs(GT_SUB)) - return; - - GenTree* op1 = node->gtGetOp1(); - GenTree* op2 = node->gtGetOp2(); - - if (!(node->TypeIs(TYP_INT, TYP_LONG) && op1->OperIs(GT_LCL_VAR))) - return; - - if (!op2->OperIs(GT_LSH)) - return; - - GenTree* lsh = op2; - GenTree* div = lsh->gtGetOp1(); - GenTree* shift = lsh->gtGetOp2(); - if (div->OperIs(GT_DIV) && shift->IsIntegralConst()) - { - GenTree* a = div->gtGetOp1(); - GenTree* cns = div->gtGetOp2(); - if (a->OperIs(GT_LCL_VAR) && cns->IsIntegralConstPow2() && - op1->AsLclVar()->GetLclNum() == a->AsLclVar()->GetLclNum()) - { - size_t shiftValue = shift->AsIntConCommon()->IntegralValue(); - size_t cnsValue = cns->AsIntConCommon()->IntegralValue(); - if ((cnsValue >> shiftValue) == 1) - { - node->ChangeOper(GT_MOD); - node->AsOp()->gtOp2 = cns; - BlockRange().Remove(lsh); - BlockRange().Remove(div); - BlockRange().Remove(a); - BlockRange().Remove(shift); - } - } - } -} -#endif - #ifdef DEBUG void Rationalizer::ValidateStatement(Statement* stmt, BasicBlock* block) @@ -563,10 +524,6 @@ void Rationalizer::RewriteAddress(LIR::Use& use) JITDUMP("Rewriting GT_ADDR(GT_IND(X)) to X:\n"); } - else - { - unreached(); - } DISPTREERANGE(BlockRange(), use.Def()); JITDUMP("\n"); @@ -599,6 +556,13 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, Compiler::Ge RewriteAssignment(use); break; + case GT_BOX: + case GT_ARR_ADDR: + // BOX/ARR_ADDR at this level are just NOPs. + use.ReplaceWith(node->gtGetOp1()); + BlockRange().Remove(node); + break; + case GT_ADDR: RewriteAddress(use); break; @@ -630,11 +594,9 @@ Compiler::fgWalkResult Rationalizer::RewriteNode(GenTree** useEdge, Compiler::Ge break; case GT_NOP: - case GT_BOX: - case GT_ARR_ADDR: - // "optNarrowTree" sometimes inserts NOP nodes between defs and uses. - // In this case, remove the NOP. BOX/ARR_ADDR are such "passthrough" - // nodes by design, and at this point we no longer need them. + // fgMorph sometimes inserts NOP nodes between defs and uses + // supposedly 'to prevent constant folding'. In this case, remove the + // NOP. if (node->gtGetOp1() != nullptr) { use.ReplaceWith(node->gtGetOp1()); @@ -818,13 +780,6 @@ PhaseStatus Rationalizer::DoPhase() m_rationalizer.RewriteIntrinsicAsUserCall(use, this->m_ancestors); } -#ifdef TARGET_ARM64 - if (node->OperIs(GT_SUB)) - { - m_rationalizer.RewriteSubLshDiv(use); - } -#endif - return Compiler::WALK_CONTINUE; } diff --git a/src/coreclr/jit/rationalize.h b/src/coreclr/jit/rationalize.h index 329fbcbd1ac24..47d355cbbd38f 100644 --- a/src/coreclr/jit/rationalize.h +++ b/src/coreclr/jit/rationalize.h @@ -58,10 +58,6 @@ class Rationalizer final : public Phase void RewriteAssignment(LIR::Use& use); void RewriteAddress(LIR::Use& use); -#ifdef TARGET_ARM64 - void RewriteSubLshDiv(GenTree** use); -#endif - // Root visitor Compiler::fgWalkResult RewriteNode(GenTree** useEdge, Compiler::GenTreeStack& parents); }; diff --git a/src/coreclr/jit/scopeinfo.cpp b/src/coreclr/jit/scopeinfo.cpp index b349d5e7aae64..6b2fcd5690eb6 100644 --- a/src/coreclr/jit/scopeinfo.cpp +++ b/src/coreclr/jit/scopeinfo.cpp @@ -295,7 +295,7 @@ void CodeGenInterface::siVarLoc::siFillStackVarLoc( case TYP_LONG: case TYP_DOUBLE: #endif // TARGET_64BIT -#if FEATURE_IMPLICIT_BYREFS +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // In the AMD64 ABI we are supposed to pass a struct by reference when its // size is not 1, 2, 4 or 8 bytes in size. During fgMorph, the compiler modifies // the IR to comply with the ABI and therefore changes the type of the lclVar @@ -314,7 +314,7 @@ void CodeGenInterface::siVarLoc::siFillStackVarLoc( this->vlType = VLT_STK_BYREF; } else -#endif // FEATURE_IMPLICIT_BYREFS +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) { this->vlType = VLT_STK; } diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index f0fc16be21c67..92706856a0dce 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -1207,7 +1207,7 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in } // Pops and returns GenTree node from importer's type stack. -// Normalizes TYP_STRUCT value in case of GT_CALL and GT_RET_EXPR. +// Normalizes TYP_STRUCT value in case of GT_CALL, GT_RET_EXPR and arg nodes. // // Arguments: // type - the type of value that the caller expects to be popped off the stack. @@ -1219,7 +1219,7 @@ const SIMDIntrinsicInfo* Compiler::getSIMDIntrinsicInfo(CORINFO_CLASS_HANDLE* in // Notes: // If the popped value is a struct, and the expected type is a simd type, it will be set // to that type, otherwise it will assert if the type being popped is not the expected type. -// + GenTree* Compiler::impSIMDPopStack(var_types type, bool expectAddr, CORINFO_CLASS_HANDLE structHandle) { StackEntry se = impPopStack(); @@ -1232,25 +1232,54 @@ GenTree* Compiler::impSIMDPopStack(var_types type, bool expectAddr, CORINFO_CLAS { assert(tree->TypeIs(TYP_BYREF, TYP_I_IMPL)); - tree = gtNewOperNode(GT_IND, type, tree); + if (tree->OperGet() == GT_ADDR) + { + tree = tree->gtGetOp1(); + } + else + { + tree = gtNewOperNode(GT_IND, type, tree); + } } - if (tree->OperIsIndir() && tree->AsIndir()->Addr()->OperIs(GT_ADDR)) + bool isParam = false; + + // If we are popping a struct type it must have a matching handle if one is specified. + // - If we have an existing 'OBJ' and 'structHandle' is specified, we will change its + // handle if it doesn't match. + // This can happen when we have a retyping of a vector that doesn't translate to any + // actual IR. + // - (If it's not an OBJ and it's used in a parameter context where it is required, + // impNormStructVal will add one). + // + if (tree->OperGet() == GT_OBJ) { - GenTree* location = tree->AsIndir()->Addr()->gtGetOp1(); - if (location->OperIs(GT_LCL_VAR) && location->TypeIs(type)) + if ((structHandle != NO_CLASS_HANDLE) && (tree->AsObj()->GetLayout()->GetClassHandle() != structHandle)) { - assert(type != TYP_STRUCT); - tree = location; + // In this case we need to retain the GT_OBJ to retype the value. + tree->AsObj()->SetLayout(typGetObjLayout(structHandle)); } + else + { + GenTree* addr = tree->AsOp()->gtOp1; + if ((addr->OperGet() == GT_ADDR) && isSIMDTypeLocal(addr->AsOp()->gtOp1)) + { + tree = addr->AsOp()->gtOp1; + } + } + } + + if (tree->OperGet() == GT_LCL_VAR) + { + isParam = lvaGetDesc(tree->AsLclVarCommon())->lvIsParam; } - // Handle calls that may return the struct via a return buffer. - if (varTypeIsStruct(tree) && tree->OperIs(GT_CALL, GT_RET_EXPR)) + // normalize TYP_STRUCT value + if (varTypeIsStruct(tree) && ((tree->OperGet() == GT_RET_EXPR) || (tree->OperGet() == GT_CALL) || isParam)) { assert(ti.IsType(TI_STRUCT)); - if (structHandle == NO_CLASS_HANDLE) + if (structHandle == nullptr) { structHandle = ti.GetClassHandleForValueClass(); } @@ -1656,15 +1685,7 @@ bool Compiler::areArrayElementsContiguous(GenTree* op1, GenTree* op2) // bool Compiler::areArgumentsContiguous(GenTree* op1, GenTree* op2) { - if (op1->TypeGet() != op2->TypeGet()) - { - return false; - } - - assert(!op1->TypeIs(TYP_STRUCT)); - - if (op1->OperIs(GT_IND) && op1->AsIndir()->Addr()->OperIs(GT_INDEX_ADDR) && op2->OperIs(GT_IND) && - op2->AsIndir()->Addr()->OperIs(GT_INDEX_ADDR)) + if (op1->OperIs(GT_IND) && op2->OperIs(GT_IND)) { return areArrayElementsContiguous(op1, op2); } diff --git a/src/coreclr/jit/targetamd64.h b/src/coreclr/jit/targetamd64.h index 645d1933e3c5a..ee2868fef4238 100644 --- a/src/coreclr/jit/targetamd64.h +++ b/src/coreclr/jit/targetamd64.h @@ -34,7 +34,6 @@ #define FEATURE_SET_FLAGS 0 // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set #define MAX_PASS_SINGLEREG_BYTES 8 // Maximum size of a struct passed in a single register (double). #ifdef UNIX_AMD64_ABI - #define FEATURE_IMPLICIT_BYREFS 0 // Support for struct parameters passed via pointers to shadow copies #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register @@ -49,7 +48,6 @@ // This is also the maximum number of registers for a MultiReg node. #else // !UNIX_AMD64_ABI #define WINDOWS_AMD64_ABI // Uses the Windows ABI for AMD64 - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies #define FEATURE_MULTIREG_ARGS_OR_RET 0 // Support for passing and/or returning single values in more than one register #define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 0 // Support for returning a single value in more than one register diff --git a/src/coreclr/jit/targetarm.h b/src/coreclr/jit/targetarm.h index 3e43eaa587141..8e93c1be08440 100644 --- a/src/coreclr/jit/targetarm.h +++ b/src/coreclr/jit/targetarm.h @@ -23,7 +23,6 @@ #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. #define FEATURE_SET_FLAGS 1 // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set - #define FEATURE_IMPLICIT_BYREFS 0 // Support for struct parameters passed via pointers to shadow copies #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register (including HFA support) #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register (including passing HFAs) #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register (including HFA returns) diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h index c9a1610aab2c5..dbfd813ac090c 100644 --- a/src/coreclr/jit/targetarm64.h +++ b/src/coreclr/jit/targetarm64.h @@ -28,7 +28,6 @@ #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. #define FEATURE_SET_FLAGS 0 // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register diff --git a/src/coreclr/jit/targetloongarch64.h b/src/coreclr/jit/targetloongarch64.h index 4190420dc5b69..f704b4b256afb 100644 --- a/src/coreclr/jit/targetloongarch64.h +++ b/src/coreclr/jit/targetloongarch64.h @@ -31,7 +31,6 @@ #define FEATURE_FASTTAILCALL 1 // Tail calls made as epilog+jmp #define FEATURE_TAILCALL_OPT 1 // opportunistic Tail calls (i.e. without ".tail" prefix) made as fast tail calls. #define FEATURE_SET_FLAGS 0 // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when the flags need to be set - #define FEATURE_IMPLICIT_BYREFS 1 // Support for struct parameters passed via pointers to shadow copies #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register #define FEATURE_MULTIREG_ARGS 1 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register diff --git a/src/coreclr/jit/targetx86.h b/src/coreclr/jit/targetx86.h index 727275654930f..044b9f201d5e3 100644 --- a/src/coreclr/jit/targetx86.h +++ b/src/coreclr/jit/targetx86.h @@ -30,7 +30,6 @@ #define FEATURE_TAILCALL_OPT 0 // opportunistic Tail calls (without ".tail" prefix) made as fast tail calls. #define FEATURE_SET_FLAGS 0 // Set to true to force the JIT to mark the trees with GTF_SET_FLAGS when // the flags need to be set - #define FEATURE_IMPLICIT_BYREFS 0 // Support for struct parameters passed via pointers to shadow copies #define FEATURE_MULTIREG_ARGS_OR_RET 1 // Support for passing and/or returning single values in more than one register #define FEATURE_MULTIREG_ARGS 0 // Support for passing a single argument in more than one register #define FEATURE_MULTIREG_RET 1 // Support for returning a single value in more than one register diff --git a/src/coreclr/jit/unwind.cpp b/src/coreclr/jit/unwind.cpp index 63c4ed716cf39..6ad60a064f35c 100644 --- a/src/coreclr/jit/unwind.cpp +++ b/src/coreclr/jit/unwind.cpp @@ -69,16 +69,7 @@ void Compiler::unwindGetFuncLocations(FuncInfoDsc* func, // The hot section only goes up to the cold section assert(fgFirstFuncletBB == nullptr); -#ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting()) - { - *ppEndLoc = nullptr; // If fake-splitting, "trick" VM by pretending entire function is hot. - } - else -#endif // DEBUG - { - *ppEndLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(fgFirstColdBlock)); - } + *ppEndLoc = new (this, CMK_UnwindInfo) emitLocation(ehEmitCookie(fgFirstColdBlock)); } else { @@ -268,13 +259,6 @@ void Compiler::unwindEmitFuncCFI(FuncInfoDsc* func, void* pHotCode, void* pColdC DWORD unwindCodeBytes = 0; BYTE* pUnwindBlock = nullptr; -#ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting()) - { - pColdCode = nullptr; - } -#endif // DEBUG - if (func->startLoc == nullptr) { startOffset = 0; diff --git a/src/coreclr/jit/unwindamd64.cpp b/src/coreclr/jit/unwindamd64.cpp index 88cefbe31ed5e..2c8e90fa5a944 100644 --- a/src/coreclr/jit/unwindamd64.cpp +++ b/src/coreclr/jit/unwindamd64.cpp @@ -656,17 +656,18 @@ void Compiler::unwindReserve() // void Compiler::unwindReserveFunc(FuncInfoDsc* func) { - unwindReserveFuncHelper(func, true); - - if (fgFirstColdBlock != nullptr) - { #ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting()) - { - assert(func->funKind == FUNC_ROOT); // No splitting of funclets. - } - else + if (JitConfig.JitFakeProcedureSplitting() && (fgFirstColdBlock != nullptr)) + { + assert(func->funKind == FUNC_ROOT); // No fake-splitting of funclets. + unwindReserveFuncHelper(func, true); + } + else #endif // DEBUG + { + unwindReserveFuncHelper(func, true); + + if (fgFirstColdBlock != nullptr) { unwindReserveFuncHelper(func, false); } @@ -858,17 +859,7 @@ void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pCo if (isHotCode) { -#ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting() && (fgFirstColdBlock != nullptr)) - { - assert(endOffset <= info.compNativeCodeSize); - } - else -#endif // DEBUG - { - assert(endOffset <= info.compTotalHotCodeSize); - } - + assert(endOffset <= info.compTotalHotCodeSize); pColdCode = nullptr; } else @@ -899,17 +890,43 @@ void Compiler::unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode static_assert_no_msg(FUNC_HANDLER == (FuncKind)CORJIT_FUNC_HANDLER); static_assert_no_msg(FUNC_FILTER == (FuncKind)CORJIT_FUNC_FILTER); - unwindEmitFuncHelper(func, pHotCode, pColdCode, true); - - if (pColdCode != nullptr) - { #ifdef DEBUG - if (!JitConfig.JitFakeProcedureSplitting()) + if (JitConfig.JitFakeProcedureSplitting() && (pColdCode != nullptr)) + { + fakeUnwindEmitFuncHelper(func, pHotCode); + } + else #endif // DEBUG + { + unwindEmitFuncHelper(func, pHotCode, pColdCode, true); + + if (pColdCode != nullptr) { unwindEmitFuncHelper(func, pHotCode, pColdCode, false); } } } +#ifdef DEBUG +void Compiler::fakeUnwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode) +{ + assert(fgFirstColdBlock != nullptr); + assert(func->funKind == FUNC_ROOT); // No fake-splitting of funclets. + + const UNATIVE_OFFSET startOffset = 0; + const UNATIVE_OFFSET endOffset = info.compNativeCodeSize; + const DWORD unwindCodeBytes = sizeof(func->unwindCodes) - func->unwindCodeSlot; + BYTE* pUnwindBlock = &func->unwindCodes[func->unwindCodeSlot]; + + if (opts.dspUnwind) + { + DumpUnwindInfo(true, startOffset, endOffset, (const UNWIND_INFO* const)pUnwindBlock); + } + + // Pass pColdCode = nullptr; VM allocs unwind info for combined hot/cold section + eeAllocUnwindInfo((BYTE*)pHotCode, nullptr, startOffset, endOffset, unwindCodeBytes, pUnwindBlock, + (CorJitFuncKind)func->funKind); +} +#endif // DEBUG + #endif // TARGET_AMD64 diff --git a/src/coreclr/jit/unwindarm.cpp b/src/coreclr/jit/unwindarm.cpp index 8a14c6edbb832..1eb7456250cbb 100644 --- a/src/coreclr/jit/unwindarm.cpp +++ b/src/coreclr/jit/unwindarm.cpp @@ -563,20 +563,13 @@ void Compiler::unwindReserve() void Compiler::unwindReserveFunc(FuncInfoDsc* func) { BOOL isFunclet = (func->funKind == FUNC_ROOT) ? FALSE : TRUE; - bool funcHasColdSection = (fgFirstColdBlock != nullptr); - -#ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting() && funcHasColdSection) - { - funcHasColdSection = false; // "Trick" the VM into thinking we don't have a cold section. - } -#endif // DEBUG + bool funcHasColdSection = false; #if defined(FEATURE_CFI_SUPPORT) if (generateCFIUnwindCodes()) { DWORD unwindCodeBytes = 0; - if (funcHasColdSection) + if (fgFirstColdBlock != nullptr) { eeReserveUnwindInfo(isFunclet, true /*isColdCode*/, unwindCodeBytes); } @@ -591,7 +584,7 @@ void Compiler::unwindReserveFunc(FuncInfoDsc* func) // cold section. This needs to be done before we split into fragments, as each // of the hot and cold sections can have multiple fragments. - if (funcHasColdSection) + if (fgFirstColdBlock != NULL) { assert(!isFunclet); // TODO-CQ: support hot/cold splitting with EH @@ -602,6 +595,8 @@ void Compiler::unwindReserveFunc(FuncInfoDsc* func) func->uwiCold = new (this, CMK_UnwindInfo) UnwindInfo(); func->uwiCold->InitUnwindInfo(this, startLoc, endLoc); func->uwiCold->HotColdSplitCodes(&func->uwi); + + funcHasColdSection = true; } // First we need to split the function or funclet into fragments that are no larger @@ -1609,19 +1604,11 @@ void UnwindFragmentInfo::Allocate( UNATIVE_OFFSET endOffset; UNATIVE_OFFSET codeSize; -// We don't support hot/cold splitting with EH, so if there is cold code, this -// better not be a funclet! -// TODO-CQ: support funclets in cold code -#ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting() && (pColdCode != NULL)) - { - noway_assert(isHotCode && (funKind == CORJIT_FUNC_ROOT)); - } - else -#endif // DEBUG - { - noway_assert(isHotCode || (funKind == CORJIT_FUNC_ROOT)); - } + // We don't support hot/cold splitting with EH, so if there is cold code, this + // better not be a funclet! + // TODO-CQ: support funclets in cold code + + noway_assert(isHotCode || funKind == CORJIT_FUNC_ROOT); // Compute the final size, and start and end offsets of the fragment @@ -1669,17 +1656,7 @@ void UnwindFragmentInfo::Allocate( if (isHotCode) { -#ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting() && (pColdCode != NULL)) - { - assert(endOffset <= uwiComp->info.compNativeCodeSize); - } - else -#endif // DEBUG - { - assert(endOffset <= uwiComp->info.compTotalHotCodeSize); - } - + assert(endOffset <= uwiComp->info.compTotalHotCodeSize); pColdCode = NULL; } else diff --git a/src/coreclr/jit/unwindx86.cpp b/src/coreclr/jit/unwindx86.cpp index 32d077429af6a..bd27e46cbef49 100644 --- a/src/coreclr/jit/unwindx86.cpp +++ b/src/coreclr/jit/unwindx86.cpp @@ -113,17 +113,18 @@ void Compiler::unwindEmit(void* pHotCode, void* pColdCode) // void Compiler::unwindReserveFunc(FuncInfoDsc* func) { - unwindReserveFuncHelper(func, true); - - if (fgFirstColdBlock != nullptr) - { #ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting()) - { - assert(func->funKind == FUNC_ROOT); // No splitting of funclets. - } - else + if (JitConfig.JitFakeProcedureSplitting() && (fgFirstColdBlock != nullptr)) + { + assert(func->funKind == FUNC_ROOT); // No fake-splitting of funclets. + unwindReserveFuncHelper(func, true); + } + else #endif // DEBUG + { + unwindReserveFuncHelper(func, true); + + if (fgFirstColdBlock != nullptr) { unwindReserveFuncHelper(func, false); } @@ -163,13 +164,17 @@ void Compiler::unwindEmitFunc(FuncInfoDsc* func, void* pHotCode, void* pColdCode static_assert_no_msg(FUNC_HANDLER == (FuncKind)CORJIT_FUNC_HANDLER); static_assert_no_msg(FUNC_FILTER == (FuncKind)CORJIT_FUNC_FILTER); - unwindEmitFuncHelper(func, pHotCode, pColdCode, true); - - if (pColdCode != nullptr) - { #ifdef DEBUG - if (!JitConfig.JitFakeProcedureSplitting()) + if (JitConfig.JitFakeProcedureSplitting() && (pColdCode != nullptr)) + { + fakeUnwindEmitFuncHelper(func, pHotCode); + } + else #endif // DEBUG + { + unwindEmitFuncHelper(func, pHotCode, pColdCode, true); + + if (pColdCode != nullptr) { unwindEmitFuncHelper(func, pHotCode, pColdCode, false); } @@ -253,17 +258,7 @@ void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pCo if (isHotCode) { -#ifdef DEBUG - if (JitConfig.JitFakeProcedureSplitting() && (fgFirstColdBlock != nullptr)) - { - assert(endOffset <= info.compNativeCodeSize); - } - else -#endif // DEBUG - { - assert(endOffset <= info.compTotalHotCodeSize); - } - + assert(endOffset <= info.compTotalHotCodeSize); pColdCode = nullptr; } else @@ -281,4 +276,22 @@ void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pCo (BYTE*)&unwindInfo, (CorJitFuncKind)func->funKind); } +#ifdef DEBUG +void Compiler::fakeUnwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode) +{ + assert(fgFirstColdBlock != nullptr); + assert(func->funKind == FUNC_ROOT); // No fake-splitting of funclets. + + const UNATIVE_OFFSET startOffset = 0; + const UNATIVE_OFFSET endOffset = info.compNativeCodeSize; + + UNWIND_INFO unwindInfo; + unwindInfo.FunctionLength = (ULONG)(endOffset); + + // Pass pColdCode = nullptr; VM allocs unwind info for combined hot/cold section + eeAllocUnwindInfo((BYTE*)pHotCode, nullptr, startOffset, endOffset, sizeof(UNWIND_INFO), (BYTE*)&unwindInfo, + (CorJitFuncKind)func->funKind); +} +#endif // DEBUG + #endif // FEATURE_EH_FUNCLETS diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 3ec54f47e886f..be7fc14611f0f 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -2869,15 +2869,13 @@ ValueNum ValueNumStore::EvalFuncForConstantArgs(var_types typ, VNFunc func, Valu { int resVal = EvalOp(func, ConstantValue(arg0VN)); // Unary op on a handle results in a handle. - return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetFoldedArithOpResultHandleFlags(arg0VN)) - : VNForIntCon(resVal); + return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetHandleFlags(arg0VN)) : VNForIntCon(resVal); } case TYP_LONG: { INT64 resVal = EvalOp(func, ConstantValue(arg0VN)); // Unary op on a handle results in a handle. - return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetFoldedArithOpResultHandleFlags(arg0VN)) - : VNForLongCon(resVal); + return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetHandleFlags(arg0VN)) : VNForLongCon(resVal); } case TYP_FLOAT: { @@ -3108,7 +3106,7 @@ ValueNum ValueNumStore::EvalFuncForConstantArgs(var_types typ, VNFunc func, Valu ValueNum handleVN = IsVNHandle(arg0VN) ? arg0VN : IsVNHandle(arg1VN) ? arg1VN : NoVN; if (handleVN != NoVN) { - result = VNForHandle(ssize_t(resultVal), GetFoldedArithOpResultHandleFlags(handleVN)); + result = VNForHandle(ssize_t(resultVal), GetHandleFlags(handleVN)); // Use VN for Handle } else { @@ -3134,7 +3132,7 @@ ValueNum ValueNumStore::EvalFuncForConstantArgs(var_types typ, VNFunc func, Valu if (handleVN != NoVN) { - result = VNForHandle(ssize_t(resultVal), GetFoldedArithOpResultHandleFlags(handleVN)); + result = VNForHandle(ssize_t(resultVal), GetHandleFlags(handleVN)); // Use VN for Handle } else { @@ -4312,14 +4310,14 @@ ValueNum ValueNumStore::EvalUsingMathIdentity(var_types typ, VNFunc func, ValueN // Arguments: // block - BasicBlock where the expression that produces this value occurs. // May be nullptr to force conservative "could be anywhere" interpretation. -// type - Type of the expression in the IR +// typ - Type of the expression in the IR // // Return Value: // A new value number distinct from any previously generated, that compares as equal // to itself, but not any other value number, and is annotated with the given // type and block. -// -ValueNum ValueNumStore::VNForExpr(BasicBlock* block, var_types type) + +ValueNum ValueNumStore::VNForExpr(BasicBlock* block, var_types typ) { BasicBlock::loopNumber loopNum; if (block == nullptr) @@ -4333,7 +4331,7 @@ ValueNum ValueNumStore::VNForExpr(BasicBlock* block, var_types type) // VNForFunc(typ, func, vn) but bypasses looking in the cache // - Chunk* const c = GetAllocChunk(type, CEA_Func1); + Chunk* const c = GetAllocChunk(typ, CEA_Func1); unsigned const offsetWithinChunk = c->AllocVN(); VNDefFuncAppFlexible* fapp = c->PointerToFuncApp(offsetWithinChunk, 1); fapp->m_func = VNF_MemOpaque; @@ -4343,19 +4341,6 @@ ValueNum ValueNumStore::VNForExpr(BasicBlock* block, var_types type) return resultVN; } -//------------------------------------------------------------------------ -// VNPairForExpr - Create a "new, unique" pair of value numbers. -// -// "VNForExpr" equivalent for "ValueNumPair"s. -// -ValueNumPair ValueNumStore::VNPairForExpr(BasicBlock* block, var_types type) -{ - ValueNum uniqVN = VNForExpr(block, type); - ValueNumPair uniqVNP(uniqVN, uniqVN); - - return uniqVNP; -} - //------------------------------------------------------------------------ // VNForLoad: Get the VN for a load from a location (physical map). // @@ -5134,37 +5119,6 @@ GenTreeFlags ValueNumStore::GetHandleFlags(ValueNum vn) return handle->m_flags; } -GenTreeFlags ValueNumStore::GetFoldedArithOpResultHandleFlags(ValueNum vn) -{ - GenTreeFlags flags = GetHandleFlags(vn); - assert((flags & GTF_ICON_HDL_MASK) == flags); - - switch (flags) - { - case GTF_ICON_SCOPE_HDL: - case GTF_ICON_CLASS_HDL: - case GTF_ICON_METHOD_HDL: - case GTF_ICON_FIELD_HDL: - case GTF_ICON_TOKEN_HDL: - case GTF_ICON_STR_HDL: - case GTF_ICON_CONST_PTR: - case GTF_ICON_VARG_HDL: - case GTF_ICON_PINVKI_HDL: - case GTF_ICON_FTN_ADDR: - case GTF_ICON_CIDMID_HDL: - case GTF_ICON_TLS_HDL: - case GTF_ICON_STATIC_BOX_PTR: - return GTF_ICON_CONST_PTR; - case GTF_ICON_STATIC_HDL: - case GTF_ICON_GLOBAL_PTR: - case GTF_ICON_BBC_PTR: - return GTF_ICON_GLOBAL_PTR; - default: - assert(!"Unexpected handle type"); - return flags; - } -} - bool ValueNumStore::IsVNHandle(ValueNum vn) { if (vn == NoVN) @@ -8205,6 +8159,9 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree) break; case GT_OBJ: + noway_assert(!"GT_OBJ can not be LHS when (tree->TypeGet() != TYP_STRUCT)!"); + break; + case GT_BLK: case GT_IND: { @@ -8500,7 +8457,8 @@ void Compiler::fgValueNumberTree(GenTree* tree) { unsigned lclNum = lclFld->GetLclNum(); - if (!lvaInSsa(lclFld->GetLclNum()) || !lclFld->HasSsaName()) + // TODO-ADDR: delete the "GetSize" check once location nodes are no more. + if (!lvaInSsa(lclFld->GetLclNum()) || !lclFld->HasSsaName() || (lclFld->GetSize() == 0)) { lclFld->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, lclFld->TypeGet())); } @@ -9339,168 +9297,143 @@ void Compiler::fgValueNumberSimd(GenTreeSIMD* tree) #endif // FEATURE_SIMD #ifdef FEATURE_HW_INTRINSICS +// Does value-numbering for a GT_HWINTRINSIC node void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree) { - NamedIntrinsic intrinsicId = tree->GetHWIntrinsicId(); - GenTree* addr = nullptr; - const bool isMemoryLoad = tree->OperIsMemoryLoad(&addr); - const bool isMemoryStore = !isMemoryLoad && tree->OperIsMemoryStore(&addr); - - // We do not model HWI stores precisely. - if (isMemoryStore) + // For safety/correctness we must mutate the global heap valuenumber + // for any HW intrinsic that performs a memory store operation + if (tree->OperIsMemoryStore()) { fgMutateGcHeap(tree DEBUGARG("HWIntrinsic - MemoryStore")); } - ValueNumPair excSetPair = ValueNumStore::VNPForEmptyExcSet(); - ValueNumPair normalPair = ValueNumPair(); - if ((tree->GetOperandCount() > 2) || ((JitConfig.JitDisableSimdVN() & 2) == 2)) { - // TODO-CQ: allow intrinsics with > 2 operands to be properly VN'ed. - normalPair = vnStore->VNPairForExpr(compCurBB, tree->TypeGet()); - + // TODO-CQ: allow intrinsics with > 2 operands to be properly VN'ed, it will + // allow use to process things like Vector128.Create(1,2,3,4) etc. + // Generate unique VN for now to retaing previous behavior. + ValueNumPair vnpExcSet = vnStore->VNPForEmptyExcSet(); for (GenTree* operand : tree->Operands()) { - excSetPair = vnStore->VNPUnionExcSet(operand->gtVNPair, excSetPair); + vnpExcSet = vnStore->VNPUnionExcSet(operand->gtVNPair, vnpExcSet); } + tree->gtVNPair = vnStore->VNPUniqueWithExc(tree->TypeGet(), vnpExcSet); + return; } - else + + VNFunc func = GetVNFuncForNode(tree); + bool isMemoryLoad = tree->OperIsMemoryLoad(); + + // If we have a MemoryLoad operation we will use the fgValueNumberByrefExposedLoad + // method to assign a value number that depends upon fgCurMemoryVN[ByrefExposed] ValueNumber + // + if (isMemoryLoad) { - VNFunc func = GetVNFuncForNode(tree); - ValueNumPair resultTypeVNPair = ValueNumPair(); - bool encodeResultType = vnEncodesResultTypeForHWIntrinsic(intrinsicId); + ValueNumPair op1vnp = vnStore->VNPNormalPair(tree->Op(1)->gtVNPair); - if (encodeResultType) - { - ValueNum simdTypeVN = vnStore->VNForSimdType(tree->GetSimdSize(), tree->GetNormalizedSimdBaseJitType()); - resultTypeVNPair.SetBoth(simdTypeVN); + // The addrVN incorporates both op1's ValueNumber and the func operation + // The func is used because operations such as LoadLow and LoadHigh perform + // different operations, thus need to compute different ValueNumbers + // We don't need to encode the result type as it will be encoded by the opcode in 'func' + // TODO-Bug: some HWI loads have more than one operand, we need to encode the rest. + ValueNum addrVN = vnStore->VNForFunc(TYP_BYREF, func, op1vnp.GetLiberal()); - JITDUMP(" simdTypeVN is "); - JITDUMPEXEC(vnPrint(simdTypeVN, 1)); - JITDUMP("\n"); + // The address could point anywhere, so it is an ByrefExposed load. + // + ValueNum loadVN = fgValueNumberByrefExposedLoad(tree->TypeGet(), addrVN); + tree->gtVNPair.SetLiberal(loadVN); + tree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet())); + + for (GenTree* operand : tree->Operands()) + { + tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, vnStore->VNPExceptionSet(operand->gtVNPair)); } + fgValueNumberAddExceptionSetForIndirection(tree, tree->Op(1)); + return; + } - auto getOperandVNs = [this, addr](GenTree* operand, ValueNumPair* pNormVNPair, ValueNumPair* pExcVNPair) { - vnStore->VNPUnpackExc(operand->gtVNPair, pNormVNPair, pExcVNPair); + bool encodeResultType = vnEncodesResultTypeForHWIntrinsic(tree->GetHWIntrinsicId()); - // If we have a load operation we will use the fgValueNumberByrefExposedLoad - // method to assign a value number that depends upon the current heap state. - // - if (operand == addr) - { - // We need to "insert" the "ByrefExposedLoad" VN somewhere here. We choose - // to do so by effectively altering the semantics of "addr" operands, making - // them represent "the load", on top of which the HWI func itself is applied. - // This is a workaround, but doing this "properly" would entail adding the - // heap and type VNs to HWI load funcs themselves. - var_types loadType = operand->TypeGet(); - ValueNum loadVN = fgValueNumberByrefExposedLoad(loadType, pNormVNPair->GetLiberal()); + ValueNumPair excSetPair = ValueNumStore::VNPForEmptyExcSet(); + ValueNumPair normalPair; + ValueNumPair resvnp = ValueNumPair(); - pNormVNPair->SetLiberal(loadVN); - pNormVNPair->SetConservative(vnStore->VNForExpr(compCurBB, loadType)); - } - }; + if (encodeResultType) + { + ValueNum simdTypeVN = vnStore->VNForSimdType(tree->GetSimdSize(), tree->GetNormalizedSimdBaseJitType()); + resvnp.SetBoth(simdTypeVN); + +#ifdef DEBUG + if (verbose) + { + printf(" simdTypeVN is "); + vnPrint(simdTypeVN, 1); + printf("\n"); + } +#endif + } + + const bool isVariableNumArgs = HWIntrinsicInfo::lookupNumArgs(tree->GetHWIntrinsicId()) == -1; - const bool isVariableNumArgs = HWIntrinsicInfo::lookupNumArgs(intrinsicId) == -1; + // There are some HWINTRINSICS operations that have zero args, i.e. NI_Vector128_Zero + if (tree->GetOperandCount() == 0) + { + // Currently we don't have intrinsics with variable number of args with a parameter-less option. + assert(!isVariableNumArgs); - // There are some HWINTRINSICS operations that have zero args, i.e. NI_Vector128_Zero - if (tree->GetOperandCount() == 0) + if (encodeResultType) { - // Currently we don't have intrinsics with variable number of args with a parameter-less option. - assert(!isVariableNumArgs); + // There are zero arg HWINTRINSICS operations that encode the result type, i.e. Vector128_AllBitSet + normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, resvnp); + assert(vnStore->VNFuncArity(func) == 1); + } + else + { + normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func); + assert(vnStore->VNFuncArity(func) == 0); + } + } + else // HWINTRINSIC unary or binary operator. + { + ValueNumPair op1vnp; + ValueNumPair op1Xvnp; + vnStore->VNPUnpackExc(tree->Op(1)->gtVNPair, &op1vnp, &op1Xvnp); + + if (tree->GetOperandCount() == 1) + { + excSetPair = op1Xvnp; if (encodeResultType) { - // There are zero arg HWINTRINSICS operations that encode the result type, i.e. Vector128_AllBitSet - normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, resultTypeVNPair); - assert(vnStore->VNFuncArity(func) == 1); + normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, resvnp); + assert((vnStore->VNFuncArity(func) == 2) || isVariableNumArgs); } else { - normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func); - assert(vnStore->VNFuncArity(func) == 0); + normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp); + assert((vnStore->VNFuncArity(func) == 1) || isVariableNumArgs); } } - else // HWINTRINSIC unary or binary operator. + else { - ValueNumPair op1vnp; - ValueNumPair op1Xvnp; - getOperandVNs(tree->Op(1), &op1vnp, &op1Xvnp); + ValueNumPair op2vnp; + ValueNumPair op2Xvnp; + vnStore->VNPUnpackExc(tree->Op(2)->gtVNPair, &op2vnp, &op2Xvnp); - if (tree->GetOperandCount() == 1) + excSetPair = vnStore->VNPExcSetUnion(op1Xvnp, op2Xvnp); + if (encodeResultType) { - excSetPair = op1Xvnp; - - if (encodeResultType) - { - normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, resultTypeVNPair); - assert((vnStore->VNFuncArity(func) == 2) || isVariableNumArgs); - } - else - { - normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp); - assert((vnStore->VNFuncArity(func) == 1) || isVariableNumArgs); - } + normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, op2vnp, resvnp); + assert((vnStore->VNFuncArity(func) == 3) || isVariableNumArgs); } else { - ValueNumPair op2vnp; - ValueNumPair op2Xvnp; - getOperandVNs(tree->Op(2), &op2vnp, &op2Xvnp); - - excSetPair = vnStore->VNPExcSetUnion(op1Xvnp, op2Xvnp); - if (encodeResultType) - { - normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, op2vnp, resultTypeVNPair); - assert((vnStore->VNFuncArity(func) == 3) || isVariableNumArgs); - } - else - { - normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, op2vnp); - assert((vnStore->VNFuncArity(func) == 2) || isVariableNumArgs); - } + normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, op2vnp); + assert((vnStore->VNFuncArity(func) == 2) || isVariableNumArgs); } } } - tree->gtVNPair = vnStore->VNPWithExc(normalPair, excSetPair); - - // Currently, the only exceptions these intrinsics could throw are NREs. - // - if (isMemoryLoad || isMemoryStore) - { - // Most load operations are simple "IND(addr)" equivalents. However, there are exceptions such as AVX - // "gather" operations, where the "effective" address - one from which the actual load will be performed and - // NullReferenceExceptions are associated with does not match the value of "addr". We will punt handling those - // precisely for now. - switch (intrinsicId) - { -#ifdef TARGET_XARCH - case NI_SSE2_MaskMove: - case NI_AVX_MaskStore: - case NI_AVX2_MaskStore: - case NI_AVX_MaskLoad: - case NI_AVX2_MaskLoad: - case NI_AVX2_GatherVector128: - case NI_AVX2_GatherVector256: - case NI_AVX2_GatherMaskVector128: - case NI_AVX2_GatherMaskVector256: - { - ValueNumPair uniqAddrVNPair = vnStore->VNPairForExpr(compCurBB, TYP_BYREF); - ValueNumPair uniqExcVNPair = vnStore->VNPairForFunc(TYP_REF, VNF_NullPtrExc, uniqAddrVNPair); - ValueNumPair uniqExcSetVNPair = vnStore->VNPExcSetSingleton(uniqExcVNPair); - - tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, uniqExcSetVNPair); - } - break; -#endif // TARGET_XARCH - - default: - fgValueNumberAddExceptionSetForIndirection(tree, addr); - break; - } - } } #endif // FEATURE_HW_INTRINSICS @@ -9717,14 +9650,19 @@ void Compiler::fgValueNumberHelperCallFunc(GenTreeCall* call, VNFunc vnf, ValueN vnpUniq.SetBoth(vnStore->VNForExpr(compCurBB, call->TypeGet())); } - if (call->GetIndirectionCellArgKind() != WellKnownArg::None) +#if defined(FEATURE_READYTORUN) && (defined(TARGET_ARMARCH) || defined(TARGET_LOONGARCH64)) + if (call->IsR2RRelativeIndir()) { - // If we are VN'ing a call with indirection cell arg (e.g. because this - // is a helper in a R2R compilation) then morph should already have - // added this arg, so we do not need to use EntryPointAddrAsArg0 - // because the indirection cell itself allows us to disambiguate. +#ifdef DEBUG + GenTree* indirectCellAddress = args->GetArgByIndex(0)->GetNode(); + assert(indirectCellAddress->IsCnsIntOrI() && indirectCellAddress->GetRegNum() == REG_R2R_INDIRECT_PARAM); +#endif // DEBUG + + // For ARM indirectCellAddress is consumed by the call itself, so it should have added as an implicit argument + // in morph. So we do not need to use EntryPointAddrAsArg0, because arg0 is already an entry point addr. useEntryPointAddrAsArg0 = false; } +#endif // FEATURE_READYTORUN && (TARGET_ARMARCH || TARGET_LOONGARCH64) CallArg* curArg = &*args->Args().begin(); if (nArgs == 0) diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index 4741e6150debe..22755856066a7 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -379,8 +379,6 @@ class ValueNumStore // returns true iff vn is known to be a constant int32 that is > 0 bool IsVNPositiveInt32Constant(ValueNum vn); - GenTreeFlags GetFoldedArithOpResultHandleFlags(ValueNum vn); - public: // Initializes any static variables of ValueNumStore. static void InitValueNumStoreStatics(); @@ -687,8 +685,9 @@ class ValueNumStore op3VN.GetConservative(), op4VN.GetConservative())); } - ValueNum VNForExpr(BasicBlock* block, var_types type = TYP_UNKNOWN); - ValueNumPair VNPairForExpr(BasicBlock* block, var_types type); + // Get a new, unique value number for an expression that we're not equating to some function, + // which is the value of a tree in the given block. + ValueNum VNForExpr(BasicBlock* block, var_types typ = TYP_UNKNOWN); // This controls extra tracing of the "evaluation" of "VNF_MapSelect" functions. #define FEATURE_VN_TRACE_APPLY_SELECTORS 1 diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index 57ce0c09f283d..b76139fdb604f 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -23,18 +23,6 @@ #if defined(TARGET_OSX) && defined(TARGET_AMD64) #include -#include - -bool IsProcessTranslated() -{ - int ret = 0; - size_t size = sizeof(ret); - if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) - { - return false; - } - return ret == 1; -} #endif // TARGET_OSX && TARGET_AMD64 #ifndef TARGET_OSX @@ -77,15 +65,6 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu *pMaxExecutableCodeSize = MaxDoubleMappedSize; *pHandle = (void*)(size_t)fd; #else // !TARGET_OSX - -#ifdef TARGET_AMD64 - if (IsProcessTranslated()) - { - // Rosetta doesn't support double mapping correctly - return false; - } -#endif // TARGET_AMD64 - *pMaxExecutableCodeSize = SIZE_MAX; *pHandle = NULL; #endif // !TARGET_OSX diff --git a/src/coreclr/nativeaot/BuildIntegration/BuildIntegration.proj b/src/coreclr/nativeaot/BuildIntegration/BuildIntegration.proj index a70f6a4f801b6..624760868cf2d 100644 --- a/src/coreclr/nativeaot/BuildIntegration/BuildIntegration.proj +++ b/src/coreclr/nativeaot/BuildIntegration/BuildIntegration.proj @@ -11,11 +11,6 @@ - - - diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props index c8ef6487bd504..b150bf6392cb2 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.props @@ -89,6 +89,7 @@ The .NET Foundation licenses this file to you under the MIT license. + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.props b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.props index e0e595e2f8c98..d8c01d5a199cf 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.props +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.props @@ -86,12 +86,6 @@ The .NET Foundation licenses this file to you under the MIT license. - - - - - - diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 9f079b4323fb8..d5c08a768d970 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -46,6 +46,7 @@ The .NET Foundation licenses this file to you under the MIT license. + false true false @@ -108,7 +109,8 @@ The .NET Foundation licenses this file to you under the MIT license. - + <_ExcludedPrivateSdkAssemblies Include="$(IlcSdkPath)System.Private.Reflection.Core.dll" Condition="$(IlcDisableReflection) == 'true'" /> + @@ -148,7 +150,8 @@ The .NET Foundation licenses this file to you under the MIT license. - + <_ExcludedPrivateSdkAssemblies Include="$(IlcSdkPath)System.Private.Reflection.Core.dll" Condition="$(IlcDisableReflection) == 'true'" /> + @@ -232,14 +235,14 @@ The .NET Foundation licenses this file to you under the MIT license. - + - + diff --git a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs index 6a56d48790efc..07dd95f67c980 100644 --- a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs +++ b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs @@ -1499,7 +1499,7 @@ public IntPtr Value // Wrapper around pointers [StructLayout(LayoutKind.Sequential)] - internal readonly unsafe struct Pointer where T : unmanaged + internal unsafe readonly struct Pointer where T : unmanaged { private readonly T* _value; @@ -1514,7 +1514,7 @@ public IntPtr Value // Wrapper around pointers that might be indirected through IAT [StructLayout(LayoutKind.Sequential)] - internal readonly unsafe struct IatAwarePointer where T : unmanaged + internal unsafe readonly struct IatAwarePointer where T : unmanaged { private readonly T* _value; @@ -1546,7 +1546,7 @@ public unsafe IntPtr Value // Wrapper around relative pointers [StructLayout(LayoutKind.Sequential)] - internal readonly unsafe struct RelativePointer where T : unmanaged + internal unsafe readonly struct RelativePointer where T : unmanaged { private readonly int _value; @@ -1561,7 +1561,7 @@ public unsafe IntPtr Value // Wrapper around relative pointers that might be indirected through IAT [StructLayout(LayoutKind.Sequential)] - internal readonly unsafe struct IatAwareRelativePointer where T : unmanaged + internal unsafe readonly struct IatAwareRelativePointer where T : unmanaged { private readonly int _value; diff --git a/src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceModeOnlyAttribute.cs b/src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceModeOnlyAttribute.cs new file mode 100644 index 0000000000000..f7d6a1d315f84 --- /dev/null +++ b/src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceModeOnlyAttribute.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace System.Runtime.CompilerServices +{ + // + // Attach to classes that contain code only used in ILC /BuildType:chk builds. + // + // Any class attributed with this must have the following properties: + // + // - Class must be declared "static" + // + // - All public/internal methods must have a return type of: + // + // void + // bool + // any non-value type + // + // - All fields must be private. + // + // - Class constructor must not have externally visible side effects. + // + // + // On /BuildType:ret builds, ILC will run a special transform that + // turns all of the public and internal method bodies into + // the equivalent of: + // + // [MethodImpl(MethodImplOptions.AggressiveInlining)] + // T Foo() + // { + // return default(T); + // } + // + // It also removes all fields and private methods (including the class constructor.) + // + // The method semantics must be defined so that ret builds have + // the desired behavior with these implementations. + // + // + [AttributeUsage(AttributeTargets.Class)] + internal sealed class DeveloperExperienceModeOnlyAttribute : Attribute + { + } +} diff --git a/src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceState.cs b/src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceState.cs index 78a8de127e59f..f2e0d260b5d12 100644 --- a/src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceState.cs +++ b/src/coreclr/nativeaot/Common/src/System/Runtime/CompilerServices/DeveloperExperienceState.cs @@ -5,6 +5,7 @@ namespace System.Runtime.CompilerServices { + [DeveloperExperienceModeOnly] internal static class DeveloperExperienceState { public static bool DeveloperExperienceModeEnabled diff --git a/src/coreclr/nativeaot/Directory.Build.props b/src/coreclr/nativeaot/Directory.Build.props index bd21f742967a1..b2cbc3c9bd2b1 100644 --- a/src/coreclr/nativeaot/Directory.Build.props +++ b/src/coreclr/nativeaot/Directory.Build.props @@ -34,7 +34,7 @@ $(NoWarn);CS8602;CS8603;CS8604;CS8618;CS8625;CS8632;CS8765 - $(NoWarn);CA1810;CA1823;CA1825;CA1852;CA2208;SA1129;SA1205;SA1400;SA1517;IDE0065 + $(NoWarn);CA1810;CA1823;CA1825;CA1852;CA2208;SA1129;SA1205;SA1400;SA1517 $(NoWarn);CS3016 diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs index b277d80d79784..3b081e5d64cfc 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/RuntimeExports.cs @@ -303,7 +303,7 @@ public static unsafe int RhGetCurrentThreadStackTrace(IntPtr[] outputBuffer) // Use DllImport here instead of LibraryImport because this file is used by Test.CoreLib. [DllImport(Redhawk.BaseName)] [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })] - private static extern unsafe int RhpGetCurrentThreadStackTrace(IntPtr* pOutputBuffer, uint outputBufferLength, UIntPtr addressInCurrentFrame); + private static unsafe extern int RhpGetCurrentThreadStackTrace(IntPtr* pOutputBuffer, uint outputBufferLength, UIntPtr addressInCurrentFrame); // Worker for RhGetCurrentThreadStackTrace. RhGetCurrentThreadStackTrace just allocates a transition // frame that will be used to seed the stack trace and this method does all the real work. diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs index 62c26ccd305ef..76234dde14e4d 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ThunkPool.cs @@ -217,7 +217,7 @@ public unsafe IntPtr AllocateThunk() int thunkIndex = (int)(((nuint)(nint)nextAvailableThunkPtr) - ((nuint)(nint)nextAvailableThunkPtr & ~Constants.PageSizeMask)); Debug.Assert((thunkIndex % Constants.ThunkDataSize) == 0); - thunkIndex /= Constants.ThunkDataSize; + thunkIndex = thunkIndex / Constants.ThunkDataSize; IntPtr thunkAddress = InternalCalls.RhpGetThunkStubsBlockAddress(nextAvailableThunkPtr) + thunkIndex * Constants.ThunkCodeSize; diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index 3ad3ceba7c8f0..8ce6ea0d29672 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -245,7 +245,10 @@ add_definitions(-D_LIB) if(WIN32) add_definitions(-DFEATURE_ETW) add_definitions(-DFEATURE_EVENT_TRACE) - add_definitions(-DFEATURE_SUSPEND_REDIRECTION) + # redirection on ARM64 should work, but needs to be tested + if (CLR_CMAKE_TARGET_ARCH_AMD64) + add_definitions(-DFEATURE_SUSPEND_REDIRECTION) + endif() else() add_definitions(-DNO_UI_ASSERT) include(unix/configure.cmake) diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index 2d8d3b2b2baa2..e65889cd3fc54 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -60,30 +60,6 @@ int g_cpuFeatures = 0; EXTERN_C int g_requiredCpuFeatures; #endif -#ifdef TARGET_UNIX -static bool InitGSCookie(); - -//----------------------------------------------------------------------------- -// GSCookies (guard-stack cookies) for detecting buffer overruns -//----------------------------------------------------------------------------- - -#ifdef __APPLE__ -#define READONLY_ATTR_ARGS section("__DATA,__const") -#else -#define READONLY_ATTR_ARGS section(".rodata") -#endif -#define READONLY_ATTR __attribute__((READONLY_ATTR_ARGS)) - -// Guard-stack cookie for preventing against stack buffer overruns -typedef size_t GSCookie; - -// const is so that it gets placed in the .text section (which is read-only) -// volatile is so that accesses to it do not get optimized away because of the const -// - -extern "C" volatile READONLY_ATTR const GSCookie __security_cookie = 0; -#endif // TARGET_UNIX - static bool InitDLL(HANDLE hPalInstance) { #ifdef FEATURE_CACHED_INTERFACE_DISPATCH @@ -143,11 +119,6 @@ static bool InitDLL(HANDLE hPalInstance) return false; #endif -#ifdef TARGET_UNIX - if (!InitGSCookie()) - return false; -#endif - if (!g_CastCacheLock.InitNoThrow(CrstType::CrstCastCache)) return false; @@ -304,34 +275,6 @@ bool DetectCPUFeatures() } #endif // !USE_PORTABLE_HELPERS -#ifdef TARGET_UNIX -inline -GSCookie * GetProcessGSCookiePtr() { return const_cast(&__security_cookie); } - -bool InitGSCookie() -{ - volatile GSCookie * pGSCookiePtr = GetProcessGSCookiePtr(); - - // The GS cookie is stored in a read only data segment - if (!PalVirtualProtect((void*)pGSCookiePtr, sizeof(GSCookie), PAGE_READWRITE)) - { - return false; - } - - // REVIEW: Need something better for PAL... - GSCookie val = (GSCookie)PalGetTickCount64(); - -#ifdef _DEBUG - // In _DEBUG, always use the same value to make it easier to search for the cookie - val = (GSCookie)(0x9ABCDEF012345678); -#endif - - *pGSCookiePtr = val; - - return PalVirtualProtect((void*)pGSCookiePtr, sizeof(GSCookie), PAGE_READONLY); -} -#endif // TARGET_UNIX - #ifdef PROFILE_STARTUP #define STD_OUTPUT_HANDLE ((uint32_t)-11) diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index aa5cfeb3cde21..df0dc0a20339c 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -734,9 +734,6 @@ static int W32toUnixAccessControl(uint32_t flProtect) case PAGE_EXECUTE_READWRITE: prot = PROT_READ | PROT_WRITE | PROT_EXEC; break; - case PAGE_READONLY: - prot = PROT_READ; - break; default: ASSERT(false); break; @@ -815,11 +812,7 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalVirtualProtect(_In_ void* pAddre { int unixProtect = W32toUnixAccessControl(protect); - // mprotect expects the address to be page-aligned - uint8_t* pPageStart = ALIGN_DOWN((uint8_t*)pAddress, OS_PAGE_SIZE); - size_t memSize = ALIGN_UP((uint8_t*)pAddress + size, OS_PAGE_SIZE) - pPageStart; - - return mprotect(pPageStart, memSize, unixProtect) == 0; + return mprotect(pAddress, size, unixProtect) == 0; } REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer) diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index 7738a7455c757..4010dbea5241f 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -693,6 +693,7 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn PTR_PTR_VOID * ppvRetAddrLocation, // out GCRefKind * pRetValueKind) // out { +#if defined(TARGET_AMD64) CoffNativeMethodInfo * pNativeMethodInfo = (CoffNativeMethodInfo *)pMethodInfo; size_t unwindDataBlobSize; @@ -718,11 +719,7 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn p += sizeof(int32_t); // Decode the GC info for the current method to determine its return type - GcInfoDecoderFlags flags = DECODE_RETURN_KIND; -#if defined(TARGET_ARM) || defined(TARGET_ARM64) - flags = (GcInfoDecoderFlags)(flags | DECODE_HAS_TAILCALLS); -#endif // TARGET_ARM || TARGET_ARM64 - GcInfoDecoder decoder(GCInfoToken(p), flags); + GcInfoDecoder decoder(GCInfoToken(p), DECODE_RETURN_KIND); GCRefKind gcRefKind = GetGcRefKind(decoder.GetReturnKind()); @@ -731,11 +728,6 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn SIZE_T EstablisherFrame; PVOID HandlerData; CONTEXT context; -#ifdef _DEBUG - memset(&context, 0xDD, sizeof(context)); -#endif - -#if defined(TARGET_AMD64) context.Rsp = pRegisterSet->GetSP(); context.Rbp = pRegisterSet->GetFP(); context.Rip = pRegisterSet->GetIP(); @@ -752,55 +744,6 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn *ppvRetAddrLocation = (PTR_PTR_VOID)(context.Rsp - sizeof (PVOID)); *pRetValueKind = gcRefKind; return true; -#elif defined(TARGET_ARM64) - - if (decoder.HasTailCalls()) - { - // Do not hijack functions that have tail calls, since there are two problems: - // 1. When a function that tail calls another one is hijacked, the LR may be - // stored at a different location in the stack frame of the tail call target. - // So just by performing tail call, the hijacked location becomes invalid and - // unhijacking would corrupt stack by writing to that location. - // 2. There is a small window after the caller pops LR from the stack in its - // epilog and before the tail called function pushes LR in its prolog when - // the hijacked return address would not be not on the stack and so we would - // not be able to unhijack. - return false; - } - - context.Sp = pRegisterSet->GetSP(); - context.Fp = pRegisterSet->GetFP(); - context.Pc = pRegisterSet->GetIP(); - context.Lr = *pRegisterSet->pLR; - - KNONVOLATILE_CONTEXT_POINTERS contextPointers; -#ifdef _DEBUG - memset(&contextPointers, 0xDD, sizeof(contextPointers)); -#endif - contextPointers.Lr = pRegisterSet->pLR; - - RtlVirtualUnwind(NULL, - dac_cast(m_moduleBase), - pRegisterSet->IP, - (PRUNTIME_FUNCTION)pNativeMethodInfo->runtimeFunction, - &context, - &HandlerData, - &EstablisherFrame, - &contextPointers); - - if (contextPointers.Lr == pRegisterSet->pLR) - { - // This is the case when we are either: - // - // 1) In a leaf method that does not push LR on stack, OR - // 2) In the prolog/epilog of a non-leaf method that has not yet pushed LR on stack - // or has LR already popped off. - return false; - } - - *ppvRetAddrLocation = (PTR_PTR_VOID)contextPointers.Lr; - *pRetValueKind = gcRefKind; - return true; #else return false; #endif // defined(TARGET_AMD64) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml index 48edfc4f2540c..3aeeaf70faefd 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.xml @@ -17,7 +17,4 @@ - - - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs index a6d77cbedf7cd..0499890c36ac6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs @@ -100,7 +100,7 @@ public virtual void TryGetMethodBase(IntPtr methodStartAddress, out MethodBase m public virtual bool OnContractFailure(string? stackTrace, ContractFailureKind contractFailureKind, string? displayMessage, string userMessage, string conditionText, Exception innerException) { - Debug.WriteLine("Assertion failed: " + (displayMessage ?? "")); + Debug.WriteLine("Assertion failed: " + (displayMessage == null ? "" : displayMessage)); if (Debugger.IsAttached) Debugger.Break(); return false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs index ed04c9b860e08..d8d43f4de9065 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs @@ -6,8 +6,6 @@ using System.Collections.Generic; using Internal.Runtime.CompilerServices; -using Internal.NativeFormat; -using Internal.Metadata.NativeFormat; namespace Internal.Runtime.Augments { @@ -15,12 +13,10 @@ namespace Internal.Runtime.Augments [System.Runtime.CompilerServices.ReflectionBlocked] public abstract class TypeLoaderCallbacks { - public abstract TypeManagerHandle GetModuleForMetadataReader(MetadataReader reader); public abstract bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle); public abstract int GetThreadStaticsSizeForDynamicType(int index, out int numTlsCells); public abstract IntPtr GenericLookupFromContextAndSignature(IntPtr context, IntPtr signature, out IntPtr auxResult); public abstract bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out MethodNameAndSignature nameAndSignature, out RuntimeTypeHandle[] genericMethodArgs); - public abstract RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs); public abstract bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2); #if FEATURE_UNIVERSAL_GENERICS public abstract IntPtr GetDelegateThunk(Delegate delegateObject, int thunkKind); @@ -28,7 +24,6 @@ public abstract class TypeLoaderCallbacks public abstract IntPtr TryGetDefaultConstructorForType(RuntimeTypeHandle runtimeTypeHandle); public abstract bool TryGetGenericVirtualTargetForTypeAndSlot(RuntimeTypeHandle targetHandle, ref RuntimeTypeHandle declaringType, RuntimeTypeHandle[] genericArguments, ref string methodName, ref RuntimeSignature methodSignature, bool lookForDefaultImplementations, out IntPtr methodPointer, out IntPtr dictionaryPointer, out bool slotUpdated); public abstract bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out string fieldName); - public abstract RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName); public abstract bool TryGetPointerTypeForTargetType(RuntimeTypeHandle pointeeTypeHandle, out RuntimeTypeHandle pointerTypeHandle); public abstract bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, bool isMdArray, int rank, out RuntimeTypeHandle arrayTypeHandle); public abstract IntPtr UpdateFloatingDictionary(IntPtr context, IntPtr dictionaryPtr); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs index 4e8bfcd492dde..2ad758accd629 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs @@ -657,7 +657,7 @@ internal sealed class CustomMarshallerTable : ConcurrentUnifier + @@ -343,15 +344,9 @@ - - ArrayBuilder.cs - Utilities\LockFreeReaderHashtable.cs - - System\Collections\Generic\EnumerableExtensions.cs - System\Collections\Generic\LowLevelList.cs @@ -379,9 +374,6 @@ System\Runtime\CompilerServices\__BlockReflectionAttribute.cs - - System\Runtime\CompilerServices\DeveloperExperienceState.cs - Internal\Runtime\CanonTypeKind.cs @@ -406,145 +398,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs index 08725d5744774..69b2f50c74f53 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs @@ -897,7 +897,7 @@ internal static unsafe Array NewMultiDimArray(EETypePtr eeType, int* pLengths, i throw new OverflowException(); if (length > MaxLength) maxArrayDimensionLengthOverflow = true; - totalLength *= (ulong)length; + totalLength = totalLength * (ulong)length; if (totalLength > int.MaxValue) throw new OutOfMemoryException(); // "Array dimensions exceeded supported range." } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Environment.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Environment.NativeAot.cs index c5648c28885a3..2573576699927 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Environment.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Environment.NativeAot.cs @@ -65,17 +65,10 @@ internal static void ShutdownCore() public static int TickCount => (int)TickCount64; - private static string[]? s_commandLineArgs; - public static string[] GetCommandLineArgs() { Debug.Assert(s_commandLineArgs != null, "VM did not properly setup application."); return (string[])s_commandLineArgs.Clone(); } - - internal static void SetCommandLineArgs(string[] cmdLineArgs) - { - s_commandLineArgs = cmdLineArgs; - } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Helpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Helpers.cs new file mode 100644 index 0000000000000..23a17a0e6702c --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Helpers.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// Implements System.Type +// + +using System; +using Internal.Runtime.Augments; + +namespace System +{ + internal static class Helpers + { + public static bool TryGetEEType(this Type type, out EETypePtr eeType) + { + RuntimeTypeHandle typeHandle = RuntimeAugments.Callbacks.GetTypeHandleIfAvailable(type); + if (typeHandle.IsNull) + { + eeType = default(EETypePtr); + return false; + } + eeType = typeHandle.ToEETypePtr(); + return true; + } + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs index 9b6b704cb68fa..6d5e6e5f937e6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/MulticastDelegate.cs @@ -46,7 +46,7 @@ private bool InvocationListEquals(MulticastDelegate d) return true; } - public sealed override bool Equals([NotNullWhen(true)] object? obj) + public override sealed bool Equals([NotNullWhen(true)] object? obj) { if (obj == null) return false; @@ -90,7 +90,7 @@ public sealed override bool Equals([NotNullWhen(true)] object? obj) } } - public sealed override int GetHashCode() + public override sealed int GetHashCode() { Delegate[]? invocationList = m_helperObject as Delegate[]; if (invocationList == null) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs index 49190e8c37125..b5e8e0dc0230f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs @@ -21,7 +21,7 @@ public virtual int ILOffset } } - public virtual void BeginCatchBlock(Type? exceptionType) + public virtual void BeginCatchBlock(Type exceptionType) { } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs index 6db9cb646f91a..a3847253fa3f0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs @@ -540,7 +540,7 @@ public static unsafe string ToHexStringUnsignedLong(ulong u, bool zeroPrepad, in for (; i >= 0; i--) { chars[i] = GetHexChar((uint)(u % 16)); - u /= 16; + u = u / 16; if ((i == 0) || (!zeroPrepad && (u == 0))) break; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs index b1bb7853cd227..572a7f2829440 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.NativeAot.Unix.cs @@ -51,14 +51,7 @@ public void Throw(string libraryName) public void TrackErrorMessage(string? message) { - if (_errorMessage == null) - { - _errorMessage = Environment.NewLine; - } - if (!_errorMessage.Contains(message)) - { - _errorMessage += message + Environment.NewLine; - } + _errorMessage = message; } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index aedbe429fd00f..6ab44352da6c9 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -285,14 +285,14 @@ internal static IntPtr RhHandleAllocDependent(object primary, object secondary) [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhTypeCast_AreTypesEquivalent")] - private static extern unsafe bool AreTypesEquivalent(MethodTable* pType1, MethodTable* pType2); + private static unsafe extern bool AreTypesEquivalent(MethodTable* pType1, MethodTable* pType2); internal static unsafe bool AreTypesEquivalent(EETypePtr pType1, EETypePtr pType2) => AreTypesEquivalent(pType1.ToPointer(), pType2.ToPointer()); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhTypeCast_AreTypesAssignable")] - private static extern unsafe bool AreTypesAssignable(MethodTable* pSourceType, MethodTable* pTargetType); + private static unsafe extern bool AreTypesAssignable(MethodTable* pSourceType, MethodTable* pTargetType); internal static unsafe bool AreTypesAssignable(EETypePtr pSourceType, EETypePtr pTargetType) => AreTypesAssignable(pSourceType.ToPointer(), pTargetType.ToPointer()); @@ -303,18 +303,18 @@ internal static unsafe bool AreTypesAssignable(EETypePtr pSourceType, EETypePtr [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOf")] - private static extern unsafe object IsInstanceOf(MethodTable* pTargetType, object obj); + private static unsafe extern object IsInstanceOf(MethodTable* pTargetType, object obj); internal static unsafe object IsInstanceOf(EETypePtr pTargetType, object obj) => IsInstanceOf(pTargetType.ToPointer(), obj); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfClass")] - private static extern unsafe object IsInstanceOfClass(MethodTable* pTargetType, object obj); + private static unsafe extern object IsInstanceOfClass(MethodTable* pTargetType, object obj); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOfInterface")] - internal static extern unsafe object IsInstanceOfInterface(MethodTable* pTargetType, object obj); + internal static unsafe extern object IsInstanceOfInterface(MethodTable* pTargetType, object obj); internal static unsafe object IsInstanceOfInterface(EETypePtr pTargetType, object obj) => IsInstanceOfInterface(pTargetType.ToPointer(), obj); @@ -327,28 +327,28 @@ internal static unsafe object IsInstanceOfInterface(EETypePtr pTargetType, objec // [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhBoxAny")] - private static extern unsafe object RhBoxAny(ref byte pData, MethodTable* pEEType); + private static unsafe extern object RhBoxAny(ref byte pData, MethodTable* pEEType); internal static unsafe object RhBoxAny(ref byte pData, EETypePtr pEEType) => RhBoxAny(ref pData, pEEType.ToPointer()); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewObject")] - private static extern unsafe object RhNewObject(MethodTable* pEEType); + private static unsafe extern object RhNewObject(MethodTable* pEEType); internal static unsafe object RhNewObject(EETypePtr pEEType) => RhNewObject(pEEType.ToPointer()); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewArray")] - private static extern unsafe Array RhNewArray(MethodTable* pEEType, int length); + private static unsafe extern Array RhNewArray(MethodTable* pEEType, int length); internal static unsafe Array RhNewArray(EETypePtr pEEType, int length) => RhNewArray(pEEType.ToPointer(), length); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewString")] - internal static extern unsafe string RhNewString(MethodTable* pEEType, int length); + internal static unsafe extern string RhNewString(MethodTable* pEEType, int length); internal static unsafe string RhNewString(EETypePtr pEEType, int length) => RhNewString(pEEType.ToPointer(), length); @@ -535,19 +535,19 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhGetThreadStaticStorageForModule")] - internal static extern unsafe object[] RhGetThreadStaticStorageForModule(int moduleIndex); + internal static unsafe extern object[] RhGetThreadStaticStorageForModule(int moduleIndex); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhSetThreadStaticStorageForModule")] - internal static extern unsafe bool RhSetThreadStaticStorageForModule(object[] storage, int moduleIndex); + internal static unsafe extern bool RhSetThreadStaticStorageForModule(object[] storage, int moduleIndex); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhCurrentNativeThreadId")] - internal static extern unsafe IntPtr RhCurrentNativeThreadId(); + internal static unsafe extern IntPtr RhCurrentNativeThreadId(); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhCurrentOSThreadId")] - internal static extern unsafe ulong RhCurrentOSThreadId(); + internal static unsafe extern ulong RhCurrentOSThreadId(); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport("*", "RhGetCurrentThunkContext")] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index 433ecd599297b..83fce9bcd1cc1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -32,8 +32,9 @@ private RuntimeTypeHandle(IntPtr value) public override bool Equals(object? obj) { - if (obj is RuntimeTypeHandle handle) + if (obj is RuntimeTypeHandle) { + RuntimeTypeHandle handle = (RuntimeTypeHandle)obj; return Equals(handle); } return false; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolPreAllocatedOverlapped.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolPreAllocatedOverlapped.cs index 4556882439198..21235042d4246 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolPreAllocatedOverlapped.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolPreAllocatedOverlapped.cs @@ -7,7 +7,7 @@ namespace System.Threading { public sealed class PreAllocatedOverlapped : IDisposable, IDeferredDisposable { - internal readonly unsafe Win32ThreadPoolNativeOverlapped* _overlapped; + internal unsafe readonly Win32ThreadPoolNativeOverlapped* _overlapped; private DeferredDisposableLifetime _lifetime; [CLSCompliant(false)] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs index cad92a13fcc97..53867b10b0f3a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Type.Internal.cs @@ -3,8 +3,6 @@ using System.Reflection; -using Internal.Runtime.Augments; - namespace System { // @@ -13,24 +11,14 @@ namespace System // Before adding new entries to this, ask yourself: is it ever referenced by System.Private.CoreLib? // If not, don't put it here. Put it on RuntimeTypeInfo instead. // + // Some of these "internal" methods are declared "public" because both Reflection.Core and System.Private.CoreLib need to reference them. + // public abstract partial class Type { - internal bool TryGetEEType(out EETypePtr eeType) - { - RuntimeTypeHandle typeHandle = RuntimeAugments.Callbacks.GetTypeHandleIfAvailable(this); - if (typeHandle.IsNull) - { - eeType = default(EETypePtr); - return false; - } - eeType = typeHandle.ToEETypePtr(); - return true; - } - /// /// Return Type.Name if sufficient metadata is available to do so - otherwise return null. /// - public string? InternalNameIfAvailable + public string InternalNameIfAvailable { get { @@ -42,7 +30,7 @@ internal bool TryGetEEType(out EETypePtr eeType) /// /// Return Type.Name if sufficient metadata is available to do so - otherwise return null and set "rootCauseForFailure" to an object to pass to MissingMetadataException. /// - internal virtual string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) => Name; + public virtual string InternalGetNameIfAvailable(ref Type? rootCauseForFailure) => Name; /// /// Return Type.Name if sufficient metadata is available to do so - otherwise return a default (non-null) string. @@ -51,7 +39,8 @@ internal string NameOrDefault { get { - return InternalNameIfAvailable ?? DefaultTypeNameWhenMissingMetadata; + string name = InternalNameIfAvailable; + return name != null ? name : DefaultTypeNameWhenMissingMetadata; } } @@ -84,7 +73,7 @@ internal string FullNameOrDefault // // The Project N version takes a raw metadata handle rather than a completed type so that it remains robust in the face of missing metadata. // - internal string FormatTypeNameForReflection() + public string FormatTypeNameForReflection() { try { @@ -98,7 +87,8 @@ internal string FormatTypeNameForReflection() rootElementType = rootElementType.GetElementType()!; if (rootElementType.IsNested) { - return InternalNameIfAvailable ?? DefaultTypeNameWhenMissingMetadata; + string name = InternalNameIfAvailable; + return name == null ? DefaultTypeNameWhenMissingMetadata : name; } // Legacy: why removing "System"? Is it just because C# has keywords for these types? @@ -119,6 +109,6 @@ internal string FormatTypeNameForReflection() } } - internal const string DefaultTypeNameWhenMissingMetadata = "UnknownType"; + public const string DefaultTypeNameWhenMissingMetadata = "UnknownType"; } } diff --git a/src/coreclr/nativeaot/System.Private.DisabledReflection/src/Internal/Reflection/RuntimeTypeInfo.cs b/src/coreclr/nativeaot/System.Private.DisabledReflection/src/Internal/Reflection/RuntimeTypeInfo.cs index ad9f79c9be184..24506863ab20b 100644 --- a/src/coreclr/nativeaot/System.Private.DisabledReflection/src/Internal/Reflection/RuntimeTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.DisabledReflection/src/Internal/Reflection/RuntimeTypeInfo.cs @@ -202,36 +202,6 @@ protected override bool IsPrimitiveImpl() return RuntimeAugments.IsPrimitive(_typeHandle); } - public override bool IsAssignableFrom([NotNullWhen(true)] Type c) - { - if (c == null) - return false; - - if (object.ReferenceEquals(c, this)) - return true; - - c = c.UnderlyingSystemType; - - Type typeInfo = c; - RuntimeTypeInfo toTypeInfo = this; - - if (typeInfo is not RuntimeType) - return false; // Desktop compat: If typeInfo is null, or implemented by a different Reflection implementation, return "false." - - RuntimeTypeInfo fromTypeInfo = (RuntimeTypeInfo)typeInfo; - - RuntimeTypeHandle toTypeHandle = toTypeInfo._typeHandle; - RuntimeTypeHandle fromTypeHandle = fromTypeInfo._typeHandle; - - if (RuntimeAugments.IsGenericTypeDefinition(toTypeHandle) || RuntimeAugments.IsGenericTypeDefinition(fromTypeHandle)) - throw new NotSupportedException(SR.Reflection_Disabled); - - if (RuntimeAugments.IsAssignableFrom(toTypeHandle, fromTypeHandle)) - return true; - - return false; - } - internal static RuntimeTypeInfo GetRuntimeTypeInfo(RuntimeTypeHandle typeHandle) { return RuntimeTypeTable.Table.GetOrAdd(new RuntimeTypeHandleKey(typeHandle)); diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/ILLink/ILLink.Substitutions.xml b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/ILLink/ILLink.Substitutions.xml new file mode 100644 index 0000000000000..f7df139a82b62 --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/ILLink/ILLink.Substitutions.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs index 02f6a206015db..f2065074d78b3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/Internal/Reflection/Core/Execution/ExecutionDomain.cs @@ -16,7 +16,6 @@ #endif using System.Reflection.Runtime.TypeParsing; using System.Reflection.Runtime.CustomAttributes; -using System.Runtime.CompilerServices; using Internal.Metadata.NativeFormat; using Internal.Runtime.Augments; @@ -25,8 +24,6 @@ namespace Internal.Reflection.Core.Execution // // This singleton class acts as an entrypoint from System.Private.Reflection.Execution to System.Private.Reflection.Core. // - [ReflectionBlocked] - [CLSCompliant(false)] public sealed class ExecutionDomain { internal ExecutionDomain(ReflectionDomainSetup executionDomainSetup, ExecutionEnvironment executionEnvironment) @@ -127,7 +124,7 @@ private static CoreTypeResolver CreateCoreTypeResolver(Func + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + A problem was found in this image's metadata. + + + Cannot create an instance of {0} because it is an abstract class. + + + Type initializer was not callable. + + + Cannot set a constant field. + + + A MemberInfo that matches '{0}' could not be found. + + + {0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true. + + + Method may only be called on a Type for which Type.IsGenericParameter is true. + + + A null or zero length string does not represent a valid Type. + + + The type or method has {1} generic parameter(s), but {0} generic argument(s) were provided. A generic argument must be provided for each generic parameter. + + + The object '{0}' was created by a custom ReflectionContext and cannot be used here. + + + The type '{0}' cannot be found. + + + The type '{0}' cannot be found in assembly '{1}'. + + + Cannot load assembly '{0}'. No metadata found for this assembly. + + + Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table. + + + Cannot bind to the target method because its signature is not compatible with that of the delegate type. + + + Type must derive from Delegate. + + + Cannot create a delegate on type '{0}' as it is missing metadata for the Invoke method. + + + An item with the same key has already been added. Key: {0} + + + The handle is invalid. + + + Type handle '{0}' and method handle with declaring type '{1}' are incompatible. Get RuntimeMethodHandle and declaring RuntimeTypeHandle off the same MethodBase. + + + Type handle '{0}' and field handle with declaring type '{1}' are incompatible. Get RuntimeFieldHandle and declaring RuntimeTypeHandle off the same FieldInfo. + + + Cannot resolve method {0} because the declaring type of the method handle is generic. Explicitly provide the declaring type to GetMethodFromHandle. + + + Cannot resolve field {0} because the declaring type of the field handle is generic. Explicitly provide the declaring type to GetFieldFromHandle. + + + Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true. + + + Type names passed to Assembly.GetType() must not specify an assembly. + + + Cannot add the event handler since no public add method exists for the event. + + + Cannot remove the event handler since no public remove method exists for the event. + + + {0} is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true. + + + PlatformNotSupported_MakeGenericType", @"MakeGenericType can only accept Type objects created by the runtime. + + + The type '{0}' may not be used as a type argument. + + + The type '{0}' may not be used as an array element type. + + + TypeHandles are not supported for types that return true for ContainsGenericParameters. + + + Must be an array type. + + + This operation is only valid on generic types. + + + Property get method not found. + + + Property set method not found. + + + Array may not be empty. + + + Member not found. + + + There is no metadata token available for the given member. + + + Field not found. + + + Type must be a type provided by the runtime. + + + ChangeType operation is not supported. + + + No parameterless constructor defined for this object. + + + Activation Attributes are not supported. + + + Vararg calling convention not supported. + + + Cannot create an instance of {0} because Type.ContainsGenericParameters is true. + + + Cannot dynamically create an instance of System.Void. + + + Method must be called on a Type for which Type.IsGenericParameter is false. + + + Must specify binding flags describing the invoke operation required (BindingFlags.InvokeMethod CreateInstance GetField SetField GetProperty SetProperty). + + + Named parameter array cannot be bigger than argument array. + + + Cannot specify both Get and Set on a property. + + + Cannot specify Set on a property and Invoke on a method. + + + Named parameter value must not be null. + + + Cannot specify both CreateInstance and another access type. + + + Cannot specify both Get and Set on a field. + + + Cannot specify both GetField and SetProperty. + + + Cannot specify both SetField and GetProperty. + + + Cannot specify Set on a Field and Invoke on a method. + + + All indexes must be of type Int32. + + + No arguments can be provided to Get a field value. + + + Only the field value can be specified to set a field value. + + + InvokeMember on a COM object is not supported on this platform. + + + Type must be a runtime Type object. + + + MethodInfo must be a runtime MethodInfo object. + + + Array must not be of length zero. + + + FieldInfo must be a runtime FieldInfo object. + + + Field in TypedReferences cannot be static. + + + FieldInfo does not match the target Type. + + + TypedReferences cannot be redefined as primitives. + + + TypedReference can only be made on nested value Types. + + + The TypedReference must be initialized. + + + Cannot create an abstract class. + + + Cannot create an instance of an interface. + + + Cannot create a byref of a byref: {0} + + + Cannot create a pointer to a byref: {0} + + + Literal value was not found. + + + Cannot create boxed ByRef-like values. + + + Cannot instantiate a generic type on a byref-like type. + + + Non-static method requires a target. + + + Object does not match target type. + + + Nullable object must have a value. + + + Interface maps for generic interfaces on arrays cannot be retrieved. + + + CodeBase is not supported on assemblies loaded from a single-file bundle. + + diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj new file mode 100644 index 0000000000000..a770233c1ccac --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj @@ -0,0 +1,200 @@ + + + + $(NoWarn);CS0672 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + System\NotImplemented.cs + + + + System\Collections\Generic\LowLevelList.cs + + + System\Collections\Generic\LowLevelDictionary.cs + + + Internal\LowLevelLinq\LowLevelEnumerable.cs + + + Internal\LowLevelLinq\LowLevelEnumerable.ToArray.cs + + + System\Collections\HashHelpers.cs + + + System\Collections\Generic\EnumerableExtensions.cs + + + System\Collections\Generic\Empty.cs + + + System\Collections\Concurrent\ConcurrentUnifier.cs + + + System\Collections\Concurrent\ConcurrentUnifierW.cs + + + System\Collections\Concurrent\ConcurrentUnifierWKeyed.cs + + + System\Collections\Concurrent\IKeyedItem.cs + + + System\Runtime\CompilerServices\DeveloperExperienceModeOnlyAttribute.cs + + + System\Runtime\CompilerServices\DeveloperExperienceState.cs + + + System\Runtime\CompilerServices\__BlockAllReflectionAttribute.cs + + + + + + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/ActivatorImplementation.cs similarity index 94% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/ActivatorImplementation.cs index 8e3aef57b8ca5..4370581bd7c6e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ActivatorImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/ActivatorImplementation.cs @@ -28,7 +28,7 @@ internal static class ActivatorImplementation BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance; if (nonPublic) bindingFlags |= BindingFlags.NonPublic; - ConstructorInfo? constructor = type.GetConstructor(bindingFlags, null, CallingConventions.Any, Array.Empty(), null); + ConstructorInfo constructor = type.GetConstructor(bindingFlags, null, CallingConventions.Any, Array.Empty(), null); if (constructor == null) { if (type.IsValueType) @@ -44,7 +44,7 @@ internal static class ActivatorImplementation [DebuggerGuidedStepThrough] public static object CreateInstance( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - Type type, BindingFlags bindingAttr, Binder binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) + Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) { if (type == null) throw new ArgumentNullException(nameof(type)); @@ -64,7 +64,7 @@ internal static class ActivatorImplementation args = Array.Empty(); int numArgs = args.Length; - Type?[] argTypes = new Type[numArgs]; + Type[] argTypes = new Type[numArgs]; for (int i = 0; i < numArgs; i++) { argTypes[i] = args[i]?.GetType(); @@ -88,7 +88,7 @@ internal static class ActivatorImplementation if (binder == null) binder = Type.DefaultBinder; - MethodBase invokeMethod = binder.BindToMethod(bindingAttr, matches.ToArray(), ref args, null, culture, null, out object? state); + MethodBase invokeMethod = binder.BindToMethod(bindingAttr, matches.ToArray(), ref args, null, culture, null, out object state); if (invokeMethod.GetParametersNoCopy().Length == 0) { if (args.Length != 0) @@ -132,7 +132,7 @@ private static void CreateInstanceCheckType(Type type) Type elementType = type; while (elementType.HasElementType) - elementType = elementType.GetElementType()!; + elementType = elementType.GetElementType(); if (elementType == typeof(void)) throw new NotSupportedException(SR.Acc_CreateVoid); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs index 48a2198d49bfe..d9f9c5f7148e2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseInsensitive.cs @@ -90,7 +90,7 @@ internal sealed override RuntimeTypeInfo GetTypeCoreCaseInsensitive(string fullN { string ns = namespaceHandle.ToNamespaceName(reader); if (ns.Length != 0) - ns += "."; + ns = ns + "."; ns = ns.ToLowerInvariant(); NamespaceDefinition namespaceDefinition = namespaceHandle.GetNamespaceDefinition(reader); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.GetTypeCore.CaseSensitive.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs index 93fd3bfca537b..81cf4e7a4c27e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/NativeFormat/NativeFormatRuntimeAssembly.cs @@ -120,7 +120,7 @@ protected sealed override IEnumerable TypeForwardInfos IEnumerable allNamespaceHandles = reader.GetTransitiveNamespaces(topLevelNamespaceHandles); foreach (NamespaceDefinitionHandle namespaceHandle in allNamespaceHandles) { - string? namespaceName = null; + string namespaceName = null; foreach (TypeForwarderHandle typeForwarderHandle in namespaceHandle.GetNamespaceDefinition(reader).TypeForwarders) { if (namespaceName == null) @@ -182,7 +182,7 @@ internal sealed override RuntimeAssemblyName RuntimeAssemblyName public sealed override bool Equals(object obj) { - NativeFormatRuntimeAssembly? other = obj as NativeFormatRuntimeAssembly; + NativeFormatRuntimeAssembly other = obj as NativeFormatRuntimeAssembly; return Equals(other); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs index 491acf920ec10..0234c88357b26 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Assemblies/RuntimeAssemblyInfo.cs @@ -29,7 +29,7 @@ namespace System.Reflection.Runtime.Assemblies // internal abstract partial class RuntimeAssemblyInfo : RuntimeAssembly, IEquatable { - public bool Equals(RuntimeAssemblyInfo? other) + public bool Equals(RuntimeAssemblyInfo other) { if (other == null) return false; @@ -102,7 +102,7 @@ public sealed override Type GetType(string name, bool throwOnError, bool ignoreC } #pragma warning disable 0067 // Silence warning about ModuleResolve not being used. - public sealed override event ModuleResolveEventHandler? ModuleResolve; + public sealed override event ModuleResolveEventHandler ModuleResolve; #pragma warning restore 0067 public sealed override bool ReflectionOnly => false; // ReflectionOnly loading not supported. @@ -120,14 +120,14 @@ public sealed override AssemblyName GetName() public sealed override Type[] GetForwardedTypes() { List types = new List(); - List? exceptions = null; + List exceptions = null; foreach (TypeForwardInfo typeForwardInfo in TypeForwardInfos) { string fullTypeName = typeForwardInfo.NamespaceName.Length == 0 ? typeForwardInfo.TypeName : typeForwardInfo.NamespaceName + "." + typeForwardInfo.TypeName; RuntimeAssemblyName redirectedAssemblyName = typeForwardInfo.RedirectedAssemblyName; - Type? type = null; + Type type = null; RuntimeAssemblyInfo redirectedAssembly; Exception exception = TryGetRuntimeAssembly(redirectedAssemblyName, out redirectedAssembly); if (exception == null) @@ -252,7 +252,6 @@ private CaseSensitiveTypeCache CaseSensitiveTypeTable } } -#pragma warning disable 0672 // GlobalAssemblyCache is Obsolete. public sealed override bool GlobalAssemblyCache { get @@ -260,7 +259,6 @@ public sealed override bool GlobalAssemblyCache return false; } } -#pragma warning restore 0672 public sealed override long HostContext { @@ -276,6 +274,8 @@ public sealed override Module LoadModule(string moduleName, byte[] rawModule, by throw new PlatformNotSupportedException(); } + internal const string ThrowingMessageInRAF = "This member throws an exception for assemblies embedded in a single-file app"; + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public sealed override FileStream GetFile(string name) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs similarity index 94% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs index ee55cf1087d2b..368105aa0de8a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/ConstructorPolicies.cs @@ -20,7 +20,7 @@ public sealed override IEnumerable GetDeclaredMembers(TypeInfo return typeInfo.DeclaredConstructors; } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) + public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) { Debug.Assert(reflectedType.Equals(type)); // Constructor queries are always performed as if BindingFlags.DeclaredOnly are set so the reflectedType should always be the declaring type. return type.CoreGetDeclaredConstructors(optionalNameFilter); @@ -43,7 +43,7 @@ public sealed override void GetMemberAttributes(ConstructorInfo member, out Meth isNewSlot = false; } - public sealed override bool ImplicitlyOverrides(ConstructorInfo? baseMember, ConstructorInfo? derivedMember) => false; + public sealed override bool ImplicitlyOverrides(ConstructorInfo baseMember, ConstructorInfo derivedMember) => false; public sealed override bool IsSuppressedByMoreDerivedMember(ConstructorInfo member, ConstructorInfo[] priorMembers, int startIndex, int endIndex) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs similarity index 68% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs index e8ba0e22ea9ae..59262a3315552 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/EventPolicies.cs @@ -20,7 +20,7 @@ public sealed override IEnumerable GetDeclaredMembers(TypeInfo typeIn return typeInfo.DeclaredEvents; } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) + public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredEvents(optionalNameFilter, reflectedType); } @@ -29,20 +29,7 @@ public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeType public sealed override void GetMemberAttributes(EventInfo member, out MethodAttributes visibility, out bool isStatic, out bool isVirtual, out bool isNewSlot) { - MethodInfo? accessorMethod = GetAccessorMethod(member); - if (accessorMethod == null) - { - // If we got here, this is a inherited EventInfo that only had private accessors and is now refusing to give them out - // because that's what the rules of inherited EventInfo's are. Such a EventInfo is also considered private and will never be - // given out of a Type.GetProperty() call. So all we have to do is set its visibility to Private and it will get filtered out. - // Other values need to be set to satisfy C# but they are meaningless. - visibility = MethodAttributes.Private; - isStatic = false; - isVirtual = false; - isNewSlot = true; - return; - } - + MethodInfo accessorMethod = GetAccessorMethod(member); MethodAttributes methodAttributes = accessorMethod.Attributes; visibility = methodAttributes & MethodAttributes.MemberAccessMask; isStatic = (0 != (methodAttributes & MethodAttributes.Static)); @@ -63,10 +50,10 @@ public sealed override bool IsSuppressedByMoreDerivedMember(EventInfo member, Ev return false; } - public sealed override bool ImplicitlyOverrides(EventInfo? baseMember, EventInfo? derivedMember) + public sealed override bool ImplicitlyOverrides(EventInfo baseMember, EventInfo derivedMember) { - MethodInfo? baseAccessor = GetAccessorMethod(baseMember!); - MethodInfo? derivedAccessor = GetAccessorMethod(derivedMember!); + MethodInfo baseAccessor = GetAccessorMethod(baseMember); + MethodInfo derivedAccessor = GetAccessorMethod(derivedMember); return MemberPolicies.Default.ImplicitlyOverrides(baseAccessor, derivedAccessor); } @@ -75,9 +62,10 @@ public sealed override bool OkToIgnoreAmbiguity(EventInfo m1, EventInfo m2) return false; } - private static MethodInfo? GetAccessorMethod(EventInfo e) + private static MethodInfo GetAccessorMethod(EventInfo e) { - return e.AddMethod; + MethodInfo accessor = e.AddMethod; + return accessor; } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs similarity index 95% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs index a1fe8f0c069e7..d17a43ce09252 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/FieldPolicies.cs @@ -20,7 +20,7 @@ public sealed override IEnumerable GetDeclaredMembers(TypeInfo typeIn return typeInfo.DeclaredFields; } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) + public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredFields(optionalNameFilter, reflectedType); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs index 50a665e5aea3a..cbb620e5be3c3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MemberPolicies.cs @@ -28,7 +28,7 @@ internal abstract class MemberPolicies where M : MemberInfo // Returns all of the directly declared members on the given TypeInfo whose name matches optionalNameFilter. If optionalNameFilter is null, // returns all directly declared members. // - public abstract IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType); + public abstract IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType); // // Policy to decide whether a member is considered "virtual", "virtual new" and what its member visibility is. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberTypeIndex.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MemberTypeIndex.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MemberTypeIndex.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MemberTypeIndex.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs similarity index 93% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs index 040034cb4e5e3..a88d9b76b1cee 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/MethodPolicies.cs @@ -20,7 +20,7 @@ public sealed override IEnumerable GetDeclaredMembers(TypeInfo typeI return typeInfo.DeclaredMethods; } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) + public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredMethods(optionalNameFilter, reflectedType); } @@ -36,10 +36,10 @@ public sealed override void GetMemberAttributes(MethodInfo member, out MethodAtt isNewSlot = (0 != (methodAttributes & MethodAttributes.NewSlot)); } - public sealed override bool ImplicitlyOverrides(MethodInfo? baseMember, MethodInfo? derivedMember) + public sealed override bool ImplicitlyOverrides(MethodInfo baseMember, MethodInfo derivedMember) { // TODO (https://github.com/dotnet/corert/issues/1896) Comparing signatures is fragile. The runtime and/or toolchain should have a way of sharing this info. - return AreNamesAndSignaturesEqual(baseMember!, derivedMember!); + return AreNamesAndSignaturesEqual(baseMember, derivedMember); } // diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.NativeFormat.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.NativeFormat.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/NameFilter.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs index 9fd791d0d655b..d22d42ac12e30 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/NestedTypePolicies.cs @@ -30,7 +30,7 @@ public sealed override IEnumerable GetDeclaredMembers(TypeInfo typeInfo) return typeInfo.DeclaredNestedTypes; } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) + public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) { Debug.Assert(reflectedType.Equals(type)); // NestedType queries are always performed as if BindingFlags.DeclaredOnly are set so the reflectedType should always be the declaring type. return type.CoreGetDeclaredNestedTypes(optionalNameFilter); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs similarity index 86% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs index c7752043c63b9..ee162bdfe9898 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/PropertyPolicies.cs @@ -20,7 +20,7 @@ public sealed override IEnumerable GetDeclaredMembers(TypeInfo typ return typeInfo.DeclaredProperties; } - public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter? optionalNameFilter, RuntimeTypeInfo reflectedType) + public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeTypeInfo type, NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) { return type.CoreGetDeclaredProperties(optionalNameFilter, reflectedType); } @@ -29,7 +29,7 @@ public sealed override IEnumerable CoreGetDeclaredMembers(RuntimeT public sealed override void GetMemberAttributes(PropertyInfo member, out MethodAttributes visibility, out bool isStatic, out bool isVirtual, out bool isNewSlot) { - MethodInfo? accessorMethod = GetAccessorMethod(member); + MethodInfo accessorMethod = GetAccessorMethod(member); if (accessorMethod == null) { // If we got here, this is a inherited PropertyInfo that only had private accessors and is now refusing to give them out @@ -50,10 +50,10 @@ public sealed override void GetMemberAttributes(PropertyInfo member, out MethodA isNewSlot = (0 != (methodAttributes & MethodAttributes.NewSlot)); } - public sealed override bool ImplicitlyOverrides(PropertyInfo? baseMember, PropertyInfo? derivedMember) + public sealed override bool ImplicitlyOverrides(PropertyInfo baseMember, PropertyInfo derivedMember) { - MethodInfo? baseAccessor = GetAccessorMethod(baseMember!); - MethodInfo? derivedAccessor = GetAccessorMethod(derivedMember!); + MethodInfo baseAccessor = GetAccessorMethod(baseMember); + MethodInfo derivedAccessor = GetAccessorMethod(derivedMember); return MemberPolicies.Default.ImplicitlyOverrides(baseAccessor, derivedAccessor); } @@ -63,11 +63,11 @@ public sealed override bool ImplicitlyOverrides(PropertyInfo? baseMember, Proper // public sealed override bool IsSuppressedByMoreDerivedMember(PropertyInfo member, PropertyInfo[] priorMembers, int startIndex, int endIndex) { - MethodInfo? baseAccessor = GetAccessorMethod(member); + MethodInfo baseAccessor = GetAccessorMethod(member); for (int i = startIndex; i < endIndex; i++) { PropertyInfo prior = priorMembers[i]; - MethodInfo? derivedAccessor = GetAccessorMethod(prior); + MethodInfo derivedAccessor = GetAccessorMethod(prior); if (!AreNamesAndSignaturesEqual(baseAccessor, derivedAccessor)) continue; if (derivedAccessor.IsStatic != baseAccessor.IsStatic) @@ -85,9 +85,9 @@ public sealed override bool OkToIgnoreAmbiguity(PropertyInfo m1, PropertyInfo m2 return false; } - private static MethodInfo? GetAccessorMethod(PropertyInfo property) + private static MethodInfo GetAccessorMethod(PropertyInfo property) { - MethodInfo? accessor = property.GetMethod; + MethodInfo accessor = property.GetMethod; if (accessor == null) { accessor = property.SetMethod; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs index 427d00b8d506b..d1ce2475ea8fd 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs @@ -105,7 +105,7 @@ public static QueriedMemberList Create(RuntimeTypeInfo type, string optionalN MemberPolicies policies = MemberPolicies.Default; - NameFilter? nameFilter; + NameFilter nameFilter; if (optionalNameFilter == null) nameFilter = null; else if (ignoreCase) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.Enumerator.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.Enumerator.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.Enumerator.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.Enumerator.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs index 4aadb1864c200..1674efe1ea57a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs @@ -92,14 +92,14 @@ public void CopyTo(MemberInfo[] array, int startIndex) /// /// Returns a single member, null or throws AmbigousMatchException, for the Type.Get*(string name,...) family of apis. /// - public M? Disambiguate() + public M Disambiguate() { if (_queriedMembers == null) return null; // This is an uninitialized QueryResult, which is supported and represents a 0-length list of matches. int unfilteredCount = UnfilteredCount; - M? match = null; + M match = null; for (int i = 0; i < unfilteredCount; i++) { if (_queriedMembers.Matches(i, _bindingAttr)) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs index 8d68023a81653..4f20819d1d210 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/Shared.cs @@ -20,7 +20,7 @@ internal static class Shared // // Candidates must pass this screen before we involve the binder. // - public static bool QualifiesBasedOnParameterCount(this MethodBase methodBase, BindingFlags bindingFlags, CallingConventions callConv, Type?[] argumentTypes) + public static bool QualifiesBasedOnParameterCount(this MethodBase methodBase, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes) { Debug.Assert(methodBase is not null); Debug.Assert(argumentTypes is not null); @@ -160,7 +160,7 @@ public static bool QualifiesBasedOnParameterCount(this MethodBase methodBase, Bi TypeInfo typeInfo = member.DeclaringType.GetTypeInfo(); for (;;) { - Type? baseType = typeInfo.BaseType; + Type baseType = typeInfo.BaseType; if (baseType == null) { return null; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs similarity index 94% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs index f564f311cc745..20a2d5ff1e3d4 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/NativeFormat/NativeFormatCustomAttributeData.cs @@ -127,16 +127,16 @@ internal sealed override IList GetConstructorArgum foreach (Handle fixedArgumentHandle in _customAttribute.FixedArguments) { Handle typeHandle = ctorTypeHandles[index]; - Exception? exception = null; - RuntimeTypeInfo? argumentType = typeHandle.TryResolve(_reader, new TypeContext(null, null), ref exception); + Exception exception = null; + RuntimeTypeInfo argumentType = typeHandle.TryResolve(_reader, new TypeContext(null, null), ref exception); if (argumentType == null) { if (throwIfMissingMetadata) - throw exception!; + throw exception; return null; } - Exception e = fixedArgumentHandle.TryParseConstantValue(_reader, out object? value); + Exception e = fixedArgumentHandle.TryParseConstantValue(_reader, out object value); CustomAttributeTypedArgument customAttributeTypedArgument; if (e != null) { @@ -169,17 +169,17 @@ internal sealed override IList GetNamedArguments(b string memberName = namedArgument.Name.GetString(_reader); bool isField = (namedArgument.Flags == NamedArgumentMemberKind.Field); - Exception? exception = null; - RuntimeTypeInfo? argumentType = namedArgument.Type.TryResolve(_reader, new TypeContext(null, null), ref exception); + Exception exception = null; + RuntimeTypeInfo argumentType = namedArgument.Type.TryResolve(_reader, new TypeContext(null, null), ref exception); if (argumentType == null) { if (throwIfMissingMetadata) - throw exception!; + throw exception; else return null; } - object? value; + object value; Exception e = namedArgument.Value.TryParseConstantValue(_reader, out value); if (e != null) { @@ -199,7 +199,7 @@ internal sealed override IList GetNamedArguments(b Justification = "Metadata generation ensures fields/properties referenced from attributes are preserved.")] private static CustomAttributeNamedArgument CreateCustomAttributeNamedArgument(Type attributeType, string memberName, bool isField, CustomAttributeTypedArgument typedValue) { - MemberInfo? memberInfo; + MemberInfo memberInfo; if (isField) memberInfo = attributeType.GetField(memberName, BindingFlags.Public | BindingFlags.Instance); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs index 2b964c6b0b560..867a447c8c049 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimeCustomAttributeData.cs @@ -116,7 +116,7 @@ private static string ComputeTypedArgumentString(CustomAttributeTypedArgument ca if (argumentType == null) return cat.ToString(); - object? value = cat.Value; + object value = cat.Value; if (argumentType.IsEnum) return string.Format(typed ? "{0}" : "({1}){0}", value, argumentType.FullName); @@ -134,9 +134,9 @@ private static string ComputeTypedArgumentString(CustomAttributeTypedArgument ca else if (argumentType.IsArray) { - IList array = (IList)value; + IList array = value as IList; - Type elementType = argumentType.GetElementType()!; + Type elementType = argumentType.GetElementType(); string result = string.Format(@"new {0}[{1}] {{ ", elementType.IsEnum ? elementType.FullName : elementType.Name, array.Count); for (int i = 0; i < array.Count; i++) @@ -161,7 +161,7 @@ private string LastResortToString // Wrap a custom attribute argument (or an element of an array-typed custom attribute argument) in a CustomAttributeTypeArgument structure // for insertion into a CustomAttributeData value. // - protected CustomAttributeTypedArgument WrapInCustomAttributeTypedArgument(object? value, Type argumentType) + protected CustomAttributeTypedArgument WrapInCustomAttributeTypedArgument(object value, Type argumentType) { if (argumentType == typeof(object)) { @@ -179,7 +179,7 @@ protected CustomAttributeTypedArgument WrapInCustomAttributeTypedArgument(object { if (!argumentType.IsArray) throw new BadImageFormatException(); - Type reportedElementType = argumentType.GetElementType()!; + Type reportedElementType = argumentType.GetElementType(); LowLevelListWithIList elementTypedArguments = new LowLevelListWithIList(); foreach (object elementValue in enumerableValue) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/CustomAttributes/RuntimePseudoCustomAttributeData.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DefaultDispenserPolicy.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/Dispenser.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/Dispenser.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/Dispenser.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/Dispenser.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserAlgorithm.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserFactory.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserPolicy.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserScenario.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysCreates.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatAlwaysReuses.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyIsAlive.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsKeyedValueIsAlive.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Dispensers/DispenserThatReusesAsLongAsValueIsAlive.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/NativeFormat/NativeFormatRuntimeEventInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/EventInfos/RuntimeEventInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs index 83835e4ce9e1b..40ad5cc3cf3c6 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/NativeFormat/NativeFormatRuntimeFieldInfo.cs @@ -21,7 +21,7 @@ using Internal.Reflection.Core; using Internal.Reflection.Core.Execution; -using Internal.Runtime.Augments; +using Internal.Runtime.TypeLoader; namespace System.Reflection.Runtime.FieldInfos.NativeFormat { @@ -134,13 +134,13 @@ public sealed override RuntimeFieldHandle FieldHandle { get { - return RuntimeAugments.TypeLoaderCallbacks.GetRuntimeFieldHandleForComponents( + return TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents( DeclaringType.TypeHandle, Name); } } - protected sealed override bool GetDefaultValueIfAvailable(bool raw, out object? defaultValue) + protected sealed override bool GetDefaultValueIfAvailable(bool raw, out object defaultValue) { return DefaultValueParser.GetDefaultValueIfAny(_reader, _field.DefaultValue, FieldType, CustomAttributes, raw, out defaultValue); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/FieldInfos/RuntimeFieldInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Assignability.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Assignability.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Assignability.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Assignability.cs index 61f1bb5430c53..074b49aab2e93 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Assignability.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Assignability.cs @@ -53,7 +53,7 @@ public static bool IsAssignableFrom(Type toTypeInfo, Type fromTypeInfo) // Desktop compat: IsAssignableFrom() considers T as assignable to Nullable (but does not check if T is a generic parameter.) if (!fromTypeInfo.IsGenericParameter) { - Type? nullableUnderlyingType = Nullable.GetUnderlyingType(toTypeInfo); + Type nullableUnderlyingType = Nullable.GetUnderlyingType(toTypeInfo); if (nullableUnderlyingType != null && nullableUnderlyingType.Equals(fromTypeInfo)) return true; } @@ -93,8 +93,8 @@ private static bool CanCastTo(this Type fromTypeInfo, Type toTypeInfo) } } - Type toElementTypeInfo = toTypeInfo.GetElementType()!; - Type fromElementTypeInfo = fromTypeInfo.GetElementType()!; + Type toElementTypeInfo = toTypeInfo.GetElementType(); + Type fromElementTypeInfo = fromTypeInfo.GetElementType(); return fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo); } @@ -103,8 +103,8 @@ private static bool CanCastTo(this Type fromTypeInfo, Type toTypeInfo) if (!toTypeInfo.IsByRef) return false; - Type toElementTypeInfo = toTypeInfo.GetElementType()!; - Type fromElementTypeInfo = fromTypeInfo.GetElementType()!; + Type toElementTypeInfo = toTypeInfo.GetElementType(); + Type fromElementTypeInfo = fromTypeInfo.GetElementType(); return fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo); } @@ -113,8 +113,8 @@ private static bool CanCastTo(this Type fromTypeInfo, Type toTypeInfo) if (!toTypeInfo.IsPointer) return false; - Type toElementTypeInfo = toTypeInfo.GetElementType()!; - Type fromElementTypeInfo = fromTypeInfo.GetElementType()!; + Type toElementTypeInfo = toTypeInfo.GetElementType(); + Type fromElementTypeInfo = fromTypeInfo.GetElementType(); return fromElementTypeInfo.IsElementTypeCompatibleWith(toElementTypeInfo); } @@ -169,7 +169,7 @@ private static bool CanCastTo(this Type fromTypeInfo, Type toTypeInfo) Type walk = fromTypeInfo; for (;;) { - Type? baseType = walk.BaseType; + Type baseType = walk.BaseType; if (baseType == null) return false; walk = baseType; @@ -358,7 +358,7 @@ private static bool CanCastArrayToInterface(this Type fromTypeInfo, Type toTypeI Type toElementTypeInfo = toTypeGenericTypeArguments[0]; Type toTypeGenericTypeDefinition = toTypeInfo.GetGenericTypeDefinition(); - Type fromElementTypeInfo = fromTypeInfo.GetElementType()!; + Type fromElementTypeInfo = fromTypeInfo.GetElementType(); foreach (Type ifc in fromTypeInfo.GetInterfaces()) { if (ifc.IsConstructedGenericType) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/BlockedRuntimeTypeNameGenerator.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/BlockedRuntimeTypeNameGenerator.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/BlockedRuntimeTypeNameGenerator.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/BlockedRuntimeTypeNameGenerator.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs index 93233d1c59a56..26d2e4bc6b090 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.NativeFormat.cs @@ -32,7 +32,7 @@ namespace System.Reflection.Runtime.Assemblies //----------------------------------------------------------------------------------------------------------- internal partial class RuntimeAssemblyInfo { - static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly? runtimeAssembly) + static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly) { if (bindResult.Reader != null) runtimeAssembly = NativeFormatRuntimeAssembly.GetRuntimeAssembly(bindResult.Reader, bindResult.ScopeDefinitionHandle, bindResult.OverflowScopes); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs index 730215bdbab6a..e524aa3bb8b85 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Dispensers.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs @@ -117,7 +117,7 @@ internal static Exception TryGetRuntimeAssembly(RuntimeAssemblyName assemblyRefN private static RuntimeAssembly GetRuntimeAssembly(AssemblyBindResult bindResult, string assemblyPath = null) { - RuntimeAssembly? result = null; + RuntimeAssembly result = null; GetNativeFormatRuntimeAssembly(bindResult, ref result); if (result != null) @@ -131,8 +131,8 @@ private static RuntimeAssembly GetRuntimeAssembly(AssemblyBindResult bindResult, } // Use C# partial method feature to avoid complex #if logic, whichever code files are included will drive behavior - static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly? runtimeAssembly); - static partial void GetEcmaRuntimeAssembly(AssemblyBindResult bindResult, string assemblyPath, ref RuntimeAssembly? runtimeAssembly); + static partial void GetNativeFormatRuntimeAssembly(AssemblyBindResult bindResult, ref RuntimeAssembly runtimeAssembly); + static partial void GetEcmaRuntimeAssembly(AssemblyBindResult bindResult, string assemblyPath, ref RuntimeAssembly runtimeAssembly); } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Helpers.NativeFormat.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Helpers.NativeFormat.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Helpers.cs similarity index 94% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Helpers.cs index 51847c8e868c3..2541bc6050666 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/Helpers.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Helpers.cs @@ -78,7 +78,7 @@ public static RuntimeNamedTypeInfo CastToRuntimeNamedTypeInfo(this Type type) public static RuntimeTypeInfo CastToRuntimeTypeInfo(this Type type) { Debug.Assert(type == null || type is RuntimeTypeInfo); - return (RuntimeTypeInfo)type!; + return (RuntimeTypeInfo)type; } public static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable enumeration) @@ -161,12 +161,16 @@ public static RuntimeMethodInfo GetInvokeMethod(this RuntimeTypeInfo delegateTyp { Debug.Assert(delegateType.IsDelegate); - MethodInfo? invokeMethod = delegateType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); + MethodInfo invokeMethod = delegateType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly); if (invokeMethod == null) { // No Invoke method found. Since delegate types are compiler constructed, the most likely cause is missing metadata rather than // a missing Invoke method. - throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(delegateType); + + // We're deliberating calling FullName rather than ToString() because if it's the type that's missing metadata, + // the FullName property constructs a more informative MissingMetadataException than we can. + string fullName = delegateType.FullName; + throw new MissingMetadataException(SR.Format(SR.Arg_InvokeMethodMissingMetadata, fullName)); // No invoke method found. } return (RuntimeMethodInfo)invokeMethod; } @@ -203,7 +207,7 @@ public static object[] InstantiateAsArray(this IEnumerable return result; } - public static bool GetCustomAttributeDefaultValueIfAny(IEnumerable customAttributes, bool raw, out object? defaultValue) + public static bool GetCustomAttributeDefaultValueIfAny(IEnumerable customAttributes, bool raw, out object defaultValue) { // Legacy: If there are multiple default value attribute, the desktop picks one at random (and so do we...) foreach (CustomAttributeData cad in customAttributes) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/IRuntimeMemberInfoWithNoMetadataDefinition.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/IRuntimeMemberInfoWithNoMetadataDefinition.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/IRuntimeMemberInfoWithNoMetadataDefinition.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/IRuntimeMemberInfoWithNoMetadataDefinition.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/LegacyCustomAttributeApis.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ListBuilder.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ListBuilder.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ListBuilder.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs index 3a1244dee6233..1c9480246005d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs @@ -9,7 +9,6 @@ using System.Collections; using System.Collections.Generic; using System.Reflection.Runtime.Assemblies; -using System.Runtime.CompilerServices; using Internal.LowLevelLinq; using Internal.Reflection.Core; @@ -24,8 +23,6 @@ namespace System.Reflection.Runtime.General // // Collect various metadata reading tasks for better chunking... // - [ReflectionBlocked] - [CLSCompliant(false)] public static class NativeFormatMetadataReaderExtensions { public static bool StringOrNullEquals(this ConstantStringValueHandle handle, string valueOrNull, MetadataReader reader) @@ -224,8 +221,8 @@ private static Exception ParseBoxedEnumConstantValue(this ConstantBoxedEnumValue { ConstantBoxedEnumValue record = handle.GetConstantBoxedEnumValue(reader); - Exception? exception = null; - Type? enumType = record.Type.TryResolve(reader, new TypeContext(null, null), ref exception); + Exception exception = null; + Type enumType = record.Type.TryResolve(reader, new TypeContext(null, null), ref exception); if (enumType == null) { value = null; @@ -320,9 +317,9 @@ private static Exception ParseBoxedEnumConstantValue(this ConstantBoxedEnumValue } } - public static object? ParseConstantValue(this Handle handle, MetadataReader reader) + public static object ParseConstantValue(this Handle handle, MetadataReader reader) { - object? value; + object value; Exception exception = handle.TryParseConstantValue(reader, out value); if (exception != null) throw exception; @@ -362,7 +359,7 @@ public static object ParseConstantNumericValue(this Handle handle, MetadataReade } } - public static Exception TryParseConstantValue(this Handle handle, MetadataReader reader, out object? value) + public static Exception TryParseConstantValue(this Handle handle, MetadataReader reader, out object value) { HandleType handleType = handle.HandleType; switch (handleType) @@ -388,8 +385,8 @@ public static Exception TryParseConstantValue(this Handle handle, MetadataReader case HandleType.TypeReference: case HandleType.TypeSpecification: { - Exception? exception = null; - Type? type = handle.TryResolve(reader, new TypeContext(null, null), ref exception); + Exception exception = null; + Type type = handle.TryResolve(reader, new TypeContext(null, null), ref exception); value = type; return (value == null) ? exception : null; } @@ -402,7 +399,7 @@ public static Exception TryParseConstantValue(this Handle handle, MetadataReader } default: { - Exception? exception; + Exception exception; value = handle.TryParseConstantArray(reader, out exception); if (value == null) return exception; @@ -411,7 +408,7 @@ public static Exception TryParseConstantValue(this Handle handle, MetadataReader } } - private static Array TryParseConstantArray(this Handle handle, MetadataReader reader, out Exception? exception) + private static Array TryParseConstantArray(this Handle handle, MetadataReader reader, out Exception exception) { exception = null; @@ -464,11 +461,11 @@ private static Array TryParseConstantArray(this Handle handle, MetadataReader re int i = 0; foreach (Handle constantHandle in constantHandles) { - object? elementValue; + object elementValue; exception = constantHandle.TryParseConstantValue(reader, out elementValue); if (exception != null) return null; - elements[i] = (string)elementValue!; + elements[i] = (string)elementValue; i++; } return elements; @@ -477,7 +474,7 @@ private static Array TryParseConstantArray(this Handle handle, MetadataReader re case HandleType.ConstantHandleArray: { HandleCollection constantHandles = handle.ToConstantHandleArrayHandle(reader).GetConstantHandleArray(reader).Value; - object?[] elements = new object[constantHandles.Count]; + object[] elements = new object[constantHandles.Count]; int i = 0; foreach (Handle constantHandle in constantHandles) { @@ -493,12 +490,12 @@ private static Array TryParseConstantArray(this Handle handle, MetadataReader re } } - private static Array TryParseConstantEnumArray(this ConstantEnumArrayHandle handle, MetadataReader reader, out Exception? exception) + private static Array TryParseConstantEnumArray(this ConstantEnumArrayHandle handle, MetadataReader reader, out Exception exception) { exception = null; ConstantEnumArray enumArray = handle.GetConstantEnumArray(reader); - Type? elementType = enumArray.ElementType.TryResolve(reader, new TypeContext(null, null), ref exception); + Type elementType = enumArray.ElementType.TryResolve(reader, new TypeContext(null, null), ref exception); if (exception != null) return null; @@ -633,7 +630,7 @@ public static string ToNamespaceName(this NamespaceDefinitionHandle namespaceDef continue; } - throw new BadImageFormatException(); + throw new BadImageFormatException(SR.Bif_InvalidMetadata); } return ns; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NamespaceChain.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NamespaceChain.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NamespaceChain.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NamespaceChain.cs index dd52a03e6b5af..34b97186d7507 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NamespaceChain.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NamespaceChain.cs @@ -39,7 +39,7 @@ internal NamespaceChain(MetadataReader reader, NamespaceDefinitionHandle innerMo continue; } - throw new BadImageFormatException(); + throw new BadImageFormatException(SR.Bif_InvalidMetadata); } DefiningScope = currentNamespaceHandle.ToScopeDefinitionHandle(reader); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs similarity index 93% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs index 24fd595d5bd09..0da7bd27a6fd2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs @@ -8,7 +8,7 @@ namespace System.Reflection.Runtime.General.NativeFormat { internal static class DefaultValueParser { - public static bool GetDefaultValueIfAny(MetadataReader reader, Handle constantHandle, Type declaredType, IEnumerable customAttributes, bool raw, out object? defaultValue) + public static bool GetDefaultValueIfAny(MetadataReader reader, Handle constantHandle, Type declaredType, IEnumerable customAttributes, bool raw, out object defaultValue) { if (!(constantHandle.IsNull(reader))) { diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs new file mode 100644 index 0000000000000..61a8b4d76801e --- /dev/null +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NonOverriddenApis.cs @@ -0,0 +1,217 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// Why this file exists: +// +// Because the Reflection base types have so many overridable members, it becomes difficult to distinguish +// members we decided not to override vs. those we forgot to override. It would be nice if C# had a construct to +// tell the reader (and Intellisense) that we've made an explicit decision *not* to override an inherited member, +// but since it doesn't, we'll make do with this instead. +// +// In DEBUG builds, we'll add a base-delegating override so that it's clear we made an explicit decision +// to accept the base class's implementation. In RELEASE builds, we'll #if'd these out to avoid the extra metadata and runtime +// cost. That way, every overridable member is accounted for (i.e. the codebase should always be kept in a state +// where hitting "override" + SPACE never brings up additional suggestions in Intellisense.) +// +// To avoid introducing inadvertent inconsistencies between DEBUG and RELEASE behavior due to the fragile base class +// problem, only do this for public or protected members that already exist on the public api type. Since we know +// we'll never remove those members, we'll avoid the problem of "base" being compile-bound to something different +// from the runtime "base." +// + +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Reflection; +using System.Globalization; +using System.Collections.Generic; + +namespace System.Reflection.Runtime.Assemblies +{ + internal partial class RuntimeAssemblyInfo + { +#if DEBUG + [RequiresUnreferencedCode("Assembly.CreateInstance is not supported with trimming. Use Type.GetType instead.")] + public sealed override object CreateInstance(string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes) => base.CreateInstance(typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes); + [RequiresUnreferencedCode("Types might be removed")] + public sealed override Type GetType(string name) => base.GetType(name); + [RequiresUnreferencedCode("Types might be removed")] + public sealed override Type GetType(string name, bool throwOnError) => base.GetType(name, throwOnError); + public sealed override bool IsDynamic => base.IsDynamic; + public sealed override string ToString() => base.ToString(); + [RequiresAssemblyFilesAttribute("The code will return an empty string for assemblies embedded in a single-file app")] +#pragma warning disable SYSLIB0012 + public sealed override string EscapedCodeBase => base.EscapedCodeBase; +#pragma warning restore SYSLIB0012 + [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + public sealed override FileStream[] GetFiles() => base.GetFiles(); +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.MethodInfos +{ + internal abstract partial class RuntimeConstructorInfo + { +#if DEBUG + public sealed override MemberTypes MemberType => base.MemberType; +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.CustomAttributes +{ + internal abstract partial class RuntimeCustomAttributeData + { +#if DEBUG + public sealed override bool Equals(object obj) => base.Equals(obj); + public sealed override int GetHashCode() => base.GetHashCode(); +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.EventInfos +{ + internal abstract partial class RuntimeEventInfo + { +#if DEBUG + public sealed override MemberTypes MemberType => base.MemberType; + public sealed override bool IsMulticast => base.IsMulticast; + public sealed override void AddEventHandler(object target, Delegate handler) => base.AddEventHandler(target, handler); + public sealed override void RemoveEventHandler(object target, Delegate handler) => base.RemoveEventHandler(target, handler); +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.FieldInfos +{ + internal abstract partial class RuntimeFieldInfo + { +#if DEBUG + public sealed override MemberTypes MemberType => base.MemberType; + public sealed override bool IsSecurityCritical => base.IsSecurityCritical; + public sealed override bool IsSecuritySafeCritical => base.IsSecuritySafeCritical; + public sealed override bool IsSecurityTransparent => base.IsSecurityTransparent; +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.MethodInfos +{ + internal abstract partial class RuntimeMethodInfo + { +#if DEBUG + public sealed override MemberTypes MemberType => base.MemberType; +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.Modules +{ + internal abstract partial class RuntimeModule + { +#if DEBUG + [RequiresUnreferencedCode("Types might be removed")] + public sealed override Type[] FindTypes(TypeFilter filter, object filterCriteria) => base.FindTypes(filter, filterCriteria); + [RequiresUnreferencedCode("Types might be removed")] + public sealed override Type GetType(string className) => base.GetType(className); + [RequiresUnreferencedCode("Types might be removed")] + public sealed override Type GetType(string className, bool ignoreCase) => base.GetType(className, ignoreCase); + public sealed override string ToString() => base.ToString(); +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.ParameterInfos +{ + internal abstract partial class RuntimeParameterInfo + { +#if DEBUG +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.PropertyInfos +{ + internal abstract partial class RuntimePropertyInfo + { +#if DEBUG + public sealed override MemberTypes MemberType => base.MemberType; + public sealed override object GetValue(object obj, object[] index) => base.GetValue(obj, index); + public sealed override void SetValue(object obj, object value, object[] index) => base.SetValue(obj, value, index); +#endif //DEBUG + } +} + +namespace System.Reflection.Runtime.TypeInfos +{ + internal abstract partial class RuntimeTypeInfo + { +#if DEBUG + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] + public sealed override Type[] FindInterfaces(TypeFilter filter, object filterCriteria) => base.FindInterfaces(filter, filterCriteria); + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + public sealed override MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, object filterCriteria) => base.FindMembers(memberType, bindingAttr, filter, filterCriteria); + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)] + public sealed override EventInfo[] GetEvents() => base.GetEvents(); + protected sealed override bool IsContextfulImpl() => base.IsContextfulImpl(); + public sealed override bool IsSubclassOf(Type c) => base.IsSubclassOf(c); + protected sealed override bool IsMarshalByRefImpl() => base.IsMarshalByRefImpl(); + public sealed override bool IsInstanceOfType(object o) => base.IsInstanceOfType(o); + public sealed override bool IsSerializable => base.IsSerializable; + public sealed override bool IsEquivalentTo(Type other) => base.IsEquivalentTo(other); // Note: If we enable COM type equivalence, this is no longer the correct implementation. + public sealed override bool IsSignatureType => base.IsSignatureType; + + public sealed override IEnumerable DeclaredConstructors + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + get => base.DeclaredConstructors; + } + public sealed override IEnumerable DeclaredEvents + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] + get => base.DeclaredEvents; + } + public sealed override IEnumerable DeclaredFields + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] + get => base.DeclaredFields; + } + public sealed override IEnumerable DeclaredMembers + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] + get => base.DeclaredMembers; + } + public sealed override IEnumerable DeclaredMethods + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] + get => base.DeclaredMethods; + } + public sealed override IEnumerable DeclaredNestedTypes + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] + get => base.DeclaredNestedTypes; + } + public sealed override IEnumerable DeclaredProperties + { + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + get => base.DeclaredProperties; + } + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] + public sealed override EventInfo GetDeclaredEvent(string name) => base.GetDeclaredEvent(name); + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] + public sealed override FieldInfo GetDeclaredField(string name) => base.GetDeclaredField(name); + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] + public sealed override MethodInfo GetDeclaredMethod(string name) => base.GetDeclaredMethod(name); + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] + public sealed override TypeInfo GetDeclaredNestedType(string name) => base.GetDeclaredNestedType(name); + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] + public sealed override PropertyInfo GetDeclaredProperty(string name) => base.GetDeclaredProperty(name); + + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] + public sealed override IEnumerable GetDeclaredMethods(string name) => base.GetDeclaredMethods(name); +#endif //DEBUG + } +} diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QSignatureTypeHandle.NativeFormat.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QSignatureTypeHandle.NativeFormat.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs similarity index 87% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs index 59925d98a73fd..b1307eea2f27a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/QSignatureTypeHandle.cs @@ -9,12 +9,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Runtime.TypeInfos; -using System.Runtime.CompilerServices; namespace System.Reflection.Runtime.General { - [ReflectionBlocked] - [CLSCompliant(false)] public partial struct QSignatureTypeHandle { public object Reader { get { return _reader; } } @@ -26,14 +23,14 @@ public partial struct QSignatureTypeHandle internal RuntimeTypeInfo Resolve(TypeContext typeContext) { - Exception? exception = null; - RuntimeTypeInfo? runtimeType = TryResolve(typeContext, ref exception); + Exception exception = null; + RuntimeTypeInfo runtimeType = TryResolve(typeContext, ref exception); if (runtimeType == null) - throw exception!; + throw exception; return runtimeType; } - internal RuntimeTypeInfo? TryResolve(TypeContext typeContext, ref Exception? exception) + internal RuntimeTypeInfo TryResolve(TypeContext typeContext, ref Exception exception) { if (Reader is global::Internal.Metadata.NativeFormat.MetadataReader) { @@ -73,8 +70,8 @@ internal string FormatTypeName(TypeContext typeContext) // Though we wrap this in a try-catch as a failsafe, this code must still strive to avoid triggering MissingMetadata exceptions // (non-error exceptions are very annoying when debugging.) - Exception? exception = null; - RuntimeTypeInfo? runtimeType = TryResolve(typeContext, ref exception); + Exception exception = null; + RuntimeTypeInfo runtimeType = TryResolve(typeContext, ref exception); if (runtimeType == null) return Type.DefaultTypeNameWhenMissingMetadata; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs index c1321e4a4797d..0b211124f26b8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ReflectionCoreCallbacksImplementation.cs @@ -183,7 +183,7 @@ private static FieldInfo GetFieldInfo(RuntimeTypeHandle declaringTypeHandle, Fie [DebuggerStepThrough] public sealed override object ActivatorCreateInstance( [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - Type type, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) + Type type, BindingFlags bindingAttr, Binder? binder, object[]? args, CultureInfo? culture, object[]? activationAttributes) { return ActivatorImplementation.CreateInstance(type, bindingAttr, binder, args, culture, activationAttributes); } @@ -323,7 +323,7 @@ private static RuntimeMethodInfo LookupMethodForCreateDelegate(RuntimeTypeInfo r while (containingType != null) { - MethodInfo? methodInfo = containingType.GetMethod(method, 0, bindingFlags, null, parameterTypes, null); + MethodInfo methodInfo = containingType.GetMethod(method, 0, bindingFlags, null, parameterTypes, null); if (methodInfo != null && methodInfo.ReturnType.Equals(invokeMethod.ReturnType)) return (RuntimeMethodInfo)methodInfo; // This cast is safe since we already verified that containingType is runtime implemented. diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/RuntimeTypeHandleKey.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeHandleKey.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/RuntimeTypeHandleKey.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/RuntimeTypeHandleKey.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ThunkedApis.cs similarity index 95% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ThunkedApis.cs index 1eb4d3dcd69ab..295c9f8777aa7 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ThunkedApis.cs @@ -41,7 +41,7 @@ public sealed override Stream GetManifestResourceStream(Type type, string name) } else { - string? nameSpace = type.Namespace; + string nameSpace = type.Namespace; if (nameSpace != null) { sb.Append(nameSpace); @@ -68,9 +68,8 @@ public override string Location } } - [Obsolete("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] - public sealed override string? CodeBase + public sealed override string CodeBase { get { @@ -176,7 +175,7 @@ public sealed override Type[] GetGenericArguments() [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2073:UnrecognizedReflectionPattern", Justification = "The returned interface is one of the interfaces implemented by this type and does have DynamicallyAccessedMemberTypes.Interfaces")] - public sealed override Type? GetInterface(string name, bool ignoreCase) + public sealed override Type GetInterface(string name, bool ignoreCase) { if (name == null) throw new ArgumentNullException("fullname" /* Yep, CoreCLR names this different than the ref assembly */); @@ -185,7 +184,7 @@ public sealed override Type[] GetGenericArguments() string ns; SplitTypeName(name, out simpleName, out ns); - Type? match = null; + Type match = null; foreach (Type ifc in ImplementedInterfaces) { string ifcSimpleName = ifc.Name; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ToStringUtils.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ToStringUtils.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ToStringUtils.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ToStringUtils.cs index 0a9ff9c82f83a..9fe84bac777ae 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ToStringUtils.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/ToStringUtils.cs @@ -21,7 +21,7 @@ public static string FormatTypeName(this QTypeDefRefOrSpec qualifiedTypeHandle, // Though we wrap this in a try-catch as a failsafe, this code must still strive to avoid triggering MissingMetadata exceptions // (non-error exceptions are very annoying when debugging.) - Exception? exception = null; + Exception exception = null; RuntimeTypeInfo runtimeType = qualifiedTypeHandle.TryResolve(typeContext, ref exception); if (runtimeType == null) return Type.DefaultTypeNameWhenMissingMetadata; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeContext.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeContext.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeContext.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeContext.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeForwardInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeForwardInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeForwardInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeForwardInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs similarity index 85% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs index 838f6a1f6dfa1..aa2a4ebf61618 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.NativeFormat.cs @@ -27,14 +27,14 @@ internal static partial class TypeResolver // internal static RuntimeTypeInfo Resolve(this Handle typeDefRefOrSpec, MetadataReader reader, TypeContext typeContext) { - Exception? exception = null; - RuntimeTypeInfo? runtimeType = typeDefRefOrSpec.TryResolve(reader, typeContext, ref exception); + Exception exception = null; + RuntimeTypeInfo runtimeType = typeDefRefOrSpec.TryResolve(reader, typeContext, ref exception); if (runtimeType == null) - throw exception!; + throw exception; return runtimeType; } - internal static RuntimeTypeInfo? TryResolve(this Handle typeDefRefOrSpec, MetadataReader reader, TypeContext typeContext, ref Exception? exception) + internal static RuntimeTypeInfo TryResolve(this Handle typeDefRefOrSpec, MetadataReader reader, TypeContext typeContext, ref Exception exception) { HandleType handleType = typeDefRefOrSpec.HandleType; if (handleType == HandleType.TypeDefinition) @@ -64,7 +64,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle // // Main routine to parse a metadata type specification signature. // - private static RuntimeTypeInfo? TryResolveTypeSignature(this TypeSpecificationHandle typeSpecHandle, MetadataReader reader, TypeContext typeContext, ref Exception? exception) + private static RuntimeTypeInfo TryResolveTypeSignature(this TypeSpecificationHandle typeSpecHandle, MetadataReader reader, TypeContext typeContext, ref Exception exception) { Handle typeHandle = typeSpecHandle.GetTypeSpecification(reader).Signature; switch (typeHandle.HandleType) @@ -75,7 +75,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle int rank = sig.Rank; if (rank <= 0) throw new BadImageFormatException(); // Bad rank. - RuntimeTypeInfo? elementType = sig.ElementType.TryResolve(reader, typeContext, ref exception); + RuntimeTypeInfo elementType = sig.ElementType.TryResolve(reader, typeContext, ref exception); if (elementType == null) return null; return elementType.GetMultiDimArrayType(rank); @@ -84,7 +84,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle case HandleType.ByReferenceSignature: { ByReferenceSignature sig = typeHandle.ToByReferenceSignatureHandle(reader).GetByReferenceSignature(reader); - RuntimeTypeInfo? targetType = sig.Type.TryResolve(reader, typeContext, ref exception); + RuntimeTypeInfo targetType = sig.Type.TryResolve(reader, typeContext, ref exception); if (targetType == null) return null; return targetType.GetByRefType(); @@ -99,7 +99,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle case HandleType.PointerSignature: { PointerSignature sig = typeHandle.ToPointerSignatureHandle(reader).GetPointerSignature(reader); - RuntimeTypeInfo? targetType = sig.Type.TryResolve(reader, typeContext, ref exception); + RuntimeTypeInfo targetType = sig.Type.TryResolve(reader, typeContext, ref exception); if (targetType == null) return null; return targetType.GetPointerType(); @@ -108,7 +108,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle case HandleType.SZArraySignature: { SZArraySignature sig = typeHandle.ToSZArraySignatureHandle(reader).GetSZArraySignature(reader); - RuntimeTypeInfo? elementType = sig.ElementType.TryResolve(reader, typeContext, ref exception); + RuntimeTypeInfo elementType = sig.ElementType.TryResolve(reader, typeContext, ref exception); if (elementType == null) return null; return elementType.GetArrayType(); @@ -122,13 +122,13 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle case HandleType.TypeInstantiationSignature: { TypeInstantiationSignature sig = typeHandle.ToTypeInstantiationSignatureHandle(reader).GetTypeInstantiationSignature(reader); - RuntimeTypeInfo? genericTypeDefinition = sig.GenericType.TryResolve(reader, typeContext, ref exception); + RuntimeTypeInfo genericTypeDefinition = sig.GenericType.TryResolve(reader, typeContext, ref exception); if (genericTypeDefinition == null) return null; LowLevelList genericTypeArguments = new LowLevelList(); foreach (Handle genericTypeArgumentHandle in sig.GenericTypeArguments) { - RuntimeTypeInfo? genericTypeArgument = genericTypeArgumentHandle.TryResolve(reader, typeContext, ref exception); + RuntimeTypeInfo genericTypeArgument = genericTypeArgumentHandle.TryResolve(reader, typeContext, ref exception); if (genericTypeArgument == null) return null; genericTypeArguments.Add(genericTypeArgument); @@ -157,7 +157,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle // [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification = "Resolves type references within metadata. We ensure metadata is consistent.")] - private static RuntimeTypeInfo? TryResolveTypeReference(this TypeReferenceHandle typeReferenceHandle, MetadataReader reader, ref Exception? exception) + private static RuntimeTypeInfo TryResolveTypeReference(this TypeReferenceHandle typeReferenceHandle, MetadataReader reader, ref Exception exception) { RuntimeTypeHandle resolvedRuntimeTypeHandle; if (ReflectionCoreExecution.ExecutionEnvironment.TryGetNamedTypeForTypeReference(reader, typeReferenceHandle, out resolvedRuntimeTypeHandle)) @@ -167,7 +167,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle string name = typeReference.TypeName.GetString(reader); Handle parent = typeReference.ParentNamespaceOrType; HandleType parentType = parent.HandleType; - TypeInfo? outerTypeInfo = null; + TypeInfo outerTypeInfo = null; // Check if this is a reference to a nested type. @@ -177,7 +177,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle } else if (parentType == HandleType.TypeReference) { - RuntimeTypeInfo? outerType = parent.ToTypeReferenceHandle(reader).TryResolveTypeReference(reader, ref exception); + RuntimeTypeInfo outerType = parent.ToTypeReferenceHandle(reader).TryResolveTypeReference(reader, ref exception); if (outerType == null) return null; outerTypeInfo = outerType; // Since we got to outerType via a metadata reference, we're assured GetTypeInfo() won't throw a MissingMetadataException. @@ -185,7 +185,7 @@ internal static RuntimeTypeInfo ResolveTypeDefinition(this TypeDefinitionHandle if (outerTypeInfo != null) { // It was a nested type. We've already resolved the containing type recursively - just find the nested among its direct children. - TypeInfo? resolvedTypeInfo = outerTypeInfo.GetDeclaredNestedType(name); + TypeInfo resolvedTypeInfo = outerTypeInfo.GetDeclaredNestedType(name); if (resolvedTypeInfo == null) { exception = ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(outerTypeInfo, name); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.cs similarity index 95% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.cs index f4665d0866567..fcf6e8d4470b0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeResolver.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeResolver.cs @@ -24,14 +24,14 @@ internal static partial class TypeResolver // internal static RuntimeTypeInfo Resolve(this QTypeDefRefOrSpec typeDefOrRefOrSpec, TypeContext typeContext) { - Exception? exception = null; + Exception exception = null; RuntimeTypeInfo runtimeType = typeDefOrRefOrSpec.TryResolve(typeContext, ref exception); if (runtimeType == null) - throw exception!; + throw exception; return runtimeType; } - internal static RuntimeTypeInfo TryResolve(this QTypeDefRefOrSpec typeDefOrRefOrSpec, TypeContext typeContext, ref Exception? exception) + internal static RuntimeTypeInfo TryResolve(this QTypeDefRefOrSpec typeDefOrRefOrSpec, TypeContext typeContext, ref Exception exception) { if (typeDefOrRefOrSpec.IsNativeFormatMetadataBased) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.NativeFormat.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.cs index cdc37f01a1b53..e9f8abb56ebfe 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/TypeUnifier.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/TypeUnifier.cs @@ -117,7 +117,7 @@ private static RuntimeConstructedGenericTypeInfo WithVerifiedTypeHandle(this Run public static RuntimeTypeInfo GetTypeForRuntimeTypeHandle(this RuntimeTypeHandle typeHandle) { - Type type = Type.GetTypeFromHandle(typeHandle)!; + Type type = Type.GetTypeFromHandle(typeHandle); return type.CastToRuntimeTypeInfo(); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs similarity index 95% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs index 3ae697e0b84ad..9a00c6995cbe3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvoker.cs @@ -21,7 +21,7 @@ public CustomMethodInvoker(Type thisType, Type[] parameterTypes, InvokerOptions _parameterTypes = parameterTypes; } - protected sealed override object? Invoke(object? thisObject, object?[] arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) + protected sealed override object Invoke(object thisObject, object[] arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { Debug.Assert(arguments != null); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodInvokerAction.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs similarity index 94% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs index 2b3c78ff34270..bda098b67e738 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.Nullable.cs @@ -77,9 +77,8 @@ private static class NullableActions map.AddMethod(type, nameof(Nullable.GetValueOrDefault), Array.Empty(), NullableGetValueOrDefault); - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:ParameterDoesntMeetParameterRequirements", - Justification = "Constructed MethodTable of a Nullable forces a constructed MethodTable of the element type")] static object NullableGetValueOrDefault(object thisObject, object[] args, + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type thisType) { if (thisObject == null) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.String.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs similarity index 93% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs index 6b81aaaeb2bf2..5848b2ed96b47 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/CustomMethodMapper.cs @@ -16,7 +16,7 @@ internal static partial class CustomMethodMapper // public static MethodInvoker GetCustomMethodInvokerIfNeeded(this MethodBase methodBase) { - Type declaringType = methodBase.DeclaringType!; + Type declaringType = methodBase.DeclaringType; bool isNullable = declaringType.IsConstructedGenericType && declaringType.GetGenericTypeDefinition() == typeof(Nullable<>); Dictionary map; @@ -27,7 +27,7 @@ public static MethodInvoker GetCustomMethodInvokerIfNeeded(this MethodBase metho else return null; - if (!map.TryGetValue(methodBase.MetadataDefinitionMethod, out CustomMethodInvokerAction? action)) + if (!(map.TryGetValue(methodBase.MetadataDefinitionMethod, out CustomMethodInvokerAction action))) return null; ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy(); @@ -52,7 +52,7 @@ private static void AddMethod(this Dictionary 0); - RuntimeTypeHandle[]? genericArgHandles; + RuntimeTypeHandle[] genericArgHandles; if (genericArgs != null) { genericArgHandles = new RuntimeTypeHandle[genericArgs.Length]; @@ -200,9 +200,9 @@ public RuntimeMethodHandle GetRuntimeMethodHandle(Type[] genericArgs) genericArgHandles = null; } - TypeManagerHandle typeManager = RuntimeAugments.TypeLoaderCallbacks.GetModuleForMetadataReader(Reader); + TypeManagerHandle typeManager = TypeLoaderEnvironment.Instance.ModuleList.GetModuleForMetadataReader(Reader); - return RuntimeAugments.TypeLoaderCallbacks.GetRuntimeMethodHandleForComponents( + return TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents( DeclaringType.TypeHandle, Name, RuntimeSignature.CreateFromMethodHandle(typeManager, MethodHandle.AsInt()), diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs similarity index 86% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs index 49e7f618c2518..945cc9e2a94d0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/OpenMethodInvoker.cs @@ -14,7 +14,7 @@ namespace System.Reflection.Runtime.MethodInfos { internal sealed class OpenMethodInvoker : MethodInvoker { - protected sealed override object? Invoke(object? thisObject, object?[] arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) + protected sealed override object Invoke(object thisObject, object[] arguments, BinderBundle binderBundle, bool wrapInTargetInvocationException) { throw new InvalidOperationException(SR.Arg_UnboundGenParam); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeClsIdNullaryConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeClsIdNullaryConstructorInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeClsIdNullaryConstructorInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeClsIdNullaryConstructorInfo.cs index 5c5d30bbb9d43..7f5dde597cce8 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeClsIdNullaryConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeClsIdNullaryConstructorInfo.cs @@ -27,7 +27,7 @@ private RuntimeCLSIDNullaryConstructorInfo(RuntimeCLSIDTypeInfo declaringType) public sealed override MethodAttributes Attributes => MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; public sealed override CallingConventions CallingConvention => CallingConventions.Standard | CallingConventions.HasThis; - public sealed override IEnumerable CustomAttributes => Array.Empty(); + public sealed override IEnumerable CustomAttributes => Empty.Enumerable; public sealed override Type DeclaringType => _declaringType; public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) @@ -50,7 +50,7 @@ public sealed override bool Equals(object obj) public sealed override int GetHashCode() => _declaringType.GetHashCode(); - public sealed override object Invoke(BindingFlags invokeAttr, Binder binder, object?[]? parameters, CultureInfo culture) + public sealed override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { throw new PlatformNotSupportedException(); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs index 53cf1f0f963cc..e46d25dd91f5d 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructedGenericMethodInfo.cs @@ -75,7 +75,7 @@ public sealed override int GetHashCode() return _genericMethodDefinition.GetHashCode(); } - internal sealed override int GenericParameterCount => _genericMethodDefinition.GenericParameterCount; + public sealed override int GenericParameterCount => _genericMethodDefinition.GenericParameterCount; public sealed override MethodInfo GetGenericMethodDefinition() { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs similarity index 94% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs index 3550d71105014..708e25cc99035 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeConstructorInfo.cs @@ -66,10 +66,10 @@ public sealed override ParameterInfo[] GetParametersNoCopy() public abstract override bool HasSameMetadataDefinitionAs(MemberInfo other); - public abstract override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture); + public abstract override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture); [DebuggerGuidedStepThrough] - public sealed override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + public sealed override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { if (parameters == null) parameters = Array.Empty(); @@ -98,9 +98,9 @@ public sealed override object Invoke(object? obj, BindingFlags invokeAttr, Binde throw; } - object? result = methodInvoker.Invoke(obj, parameters, binder, invokeAttr, culture); + object result = methodInvoker.Invoke(obj, parameters, binder, invokeAttr, culture); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); - return result!; + return result; } public abstract override MethodBase MetadataDefinitionMethod { get; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs index 409186ad65429..9220b3a0bb6eb 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeDummyMethodInfo.cs @@ -31,7 +31,7 @@ internal sealed class RuntimeDummyMethodInfo : RuntimeNamedMethodInfo public sealed override bool IsConstructedGenericMethod { get { throw NotImplemented.ByDesign; } } public sealed override bool IsGenericMethod { get { throw NotImplemented.ByDesign; } } public sealed override bool IsGenericMethodDefinition { get { throw NotImplemented.ByDesign; } } - internal sealed override int GenericParameterCount { get { throw NotImplemented.ByDesign; } } + public sealed override int GenericParameterCount { get { throw NotImplemented.ByDesign; } } public sealed override bool HasSameMetadataDefinitionAs(MemberInfo other) { throw NotImplemented.ByDesign; } public sealed override MethodImplAttributes MethodImplementationFlags { get { throw NotImplemented.ByDesign; } } public sealed override Module Module { get { throw NotImplemented.ByDesign; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs index 4892116492429..2f17ba860e949 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodHelpers.cs @@ -105,7 +105,7 @@ internal static string ComputeToString(MethodBase contextMethod, RuntimeTypeInfo { sb.Append(sep); sep = ","; - string? name = methodTypeArgument.InternalNameIfAvailable; + string name = methodTypeArgument.InternalNameIfAvailable; if (name == null) name = Type.DefaultTypeNameWhenMissingMetadata; sb.Append(methodTypeArgument.Name); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs index e9907db30eb9c..3d9fc962699bf 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs @@ -132,7 +132,7 @@ public sealed override Type[] GetGenericArguments() return RuntimeGenericArgumentsOrParameters.CloneTypeArray(); } - internal abstract override int GenericParameterCount { get; } + public abstract override int GenericParameterCount { get; } public abstract override MethodInfo GetGenericMethodDefinition(); @@ -161,12 +161,12 @@ public sealed override ParameterInfo[] GetParametersNoCopy() public abstract override bool HasSameMetadataDefinitionAs(MemberInfo other); [DebuggerGuidedStepThroughAttribute] - public sealed override object? Invoke(object? obj, BindingFlags invokeAttr, Binder binder, object?[]? parameters, CultureInfo culture) + public sealed override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { if (parameters == null) parameters = Array.Empty(); MethodInvoker methodInvoker = this.MethodInvoker; - object? result = methodInvoker.Invoke(obj, parameters, binder, invokeAttr, culture); + object result = methodInvoker.Invoke(obj, parameters, binder, invokeAttr, culture); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return result; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs index c75d371be48d7..252c556e21d24 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeNamedMethodInfo.cs @@ -117,7 +117,7 @@ public sealed override bool IsGenericMethodDefinition } } - internal sealed override int GenericParameterCount => _common.GenericParameterCount; + public sealed override int GenericParameterCount => _common.GenericParameterCount; [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")] [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] @@ -135,7 +135,7 @@ public sealed override MethodInfo MakeGenericMethod(params Type[] typeArguments) throw new ArgumentNullException(); if (typeArgument is not RuntimeType) - throw new PlatformNotSupportedException(SR.Format(SR.Reflection_CustomReflectionObjectsNotSupported, typeArguments[i])); + throw new ArgumentException(SR.Format(SR.Reflection_CustomReflectionObjectsNotSupported, typeArguments[i]), "typeArguments[" + i + "]"); // Not a runtime type. if (typeArgument.IsByRefLike) throw new BadImageFormatException(SR.CannotUseByRefLikeTypeInInstantiation); @@ -318,7 +318,7 @@ internal sealed override MethodInvoker GetUncachedMethodInvoker(RuntimeTypeInfo[ static Type Unwrap(Type t) { while (t.HasElementType) - t = t.GetElementType()!; + t = t.GetElementType(); return t; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs index acd2980e29194..030759f35f5a2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimePlainConstructorInfo.cs @@ -76,7 +76,7 @@ public sealed override Type DeclaringType } [DebuggerGuidedStepThrough] - public sealed override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + public sealed override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { if (parameters == null) parameters = Array.Empty(); @@ -86,9 +86,9 @@ public sealed override object Invoke(BindingFlags invokeAttr, Binder? binder, ob // Reflection.Core does not hardcode these special cases. It's up to the ExecutionEnvironment to steer // us the right way by coordinating the implementation of NewObject and MethodInvoker. object newObject = ReflectionCoreExecution.ExecutionEnvironment.NewObject(this.DeclaringType.TypeHandle); - object ctorAllocatedObject = this.MethodInvoker.Invoke(newObject, parameters, binder, invokeAttr, culture)!; + object ctorAllocatedObject = this.MethodInvoker.Invoke(newObject, parameters, binder, invokeAttr, culture); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); - return newObject ?? ctorAllocatedObject; + return newObject != null ? newObject : ctorAllocatedObject; } public sealed override MethodBase MetadataDefinitionMethod diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs index 939535180b69e..f6129972b3169 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticConstructorInfo.cs @@ -48,7 +48,7 @@ public sealed override IEnumerable CustomAttributes { get { - return Array.Empty(); + return Empty.Enumerable; } } @@ -77,12 +77,12 @@ public sealed override int MetadataToken } [DebuggerGuidedStepThrough] - public sealed override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + public sealed override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { if (parameters == null) parameters = Array.Empty(); - object ctorAllocatedObject = this.MethodInvoker.Invoke(null, parameters, binder, invokeAttr, culture)!; + object ctorAllocatedObject = this.MethodInvoker.Invoke(null, parameters, binder, invokeAttr, culture); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); return ctorAllocatedObject; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs index 8a03a7a2f3192..4d432d988244f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeSyntheticMethodInfo.cs @@ -50,7 +50,7 @@ public sealed override IEnumerable CustomAttributes { get { - return Array.Empty(); + return Empty.Enumerable; } } @@ -108,7 +108,7 @@ public sealed override bool IsGenericMethodDefinition } } - internal sealed override int GenericParameterCount => 0; + public sealed override int GenericParameterCount => 0; [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")] [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/SyntheticMethodId.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/VirtualRuntimeParameterInfoArray.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/NativeFormat/NativeFormatRuntimeModule.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/NativeFormat/NativeFormatRuntimeModule.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/NativeFormat/NativeFormatRuntimeModule.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/NativeFormat/NativeFormatRuntimeModule.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/RuntimeModule.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/RuntimeModule.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/RuntimeModule.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/RuntimeModule.cs index c98f84cb4f6d3..c799a3db28a5e 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/Modules/RuntimeModule.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/Modules/RuntimeModule.cs @@ -25,6 +25,8 @@ protected RuntimeModule() public abstract override IEnumerable CustomAttributes { get; } + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public sealed override string FullyQualifiedName { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs index 3a49e94a9bd35..9ca0900638452 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/NativeFormat/NativeFormatMethodParameterInfo.cs @@ -64,7 +64,7 @@ public sealed override int MetadataToken protected sealed override IEnumerable TrueCustomAttributes => RuntimeCustomAttributeData.GetCustomAttributes(this.Reader, _parameter.CustomAttributes); - protected sealed override bool GetDefaultValueIfAvailable(bool raw, out object? defaultValue) + protected sealed override bool GetDefaultValueIfAvailable(bool raw, out object defaultValue) { return DefaultValueParser.GetDefaultValueIfAny(Reader, _parameter.DefaultValue, ParameterType, CustomAttributes, raw, out defaultValue); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeFatMethodParameterInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeMethodParameterInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeParameterInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimePropertyIndexParameterInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs index 2f68d703a80df..505f8109297a4 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeSyntheticParameterInfo.cs @@ -36,7 +36,7 @@ public sealed override IEnumerable CustomAttributes { get { - return Array.Empty(); + return Empty.Enumerable; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs index b1c543238de15..cb53a3648beaa 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs @@ -34,7 +34,7 @@ public sealed override IEnumerable CustomAttributes { get { - return Array.Empty(); + return Empty.Enumerable; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/EcmaFormat/EcmaFormatRuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/EcmaFormat/EcmaFormatRuntimePropertyInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/EcmaFormat/EcmaFormatRuntimePropertyInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/EcmaFormat/EcmaFormatRuntimePropertyInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs index d87734708878c..23d45271e63a3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/NativeFormat/NativeFormatRuntimePropertyInfo.cs @@ -127,7 +127,7 @@ protected sealed override QSignatureTypeHandle PropertyTypeHandle } } - protected sealed override bool GetDefaultValueIfAny(bool raw, out object? defaultValue) + protected sealed override bool GetDefaultValueIfAny(bool raw, out object defaultValue) { return DefaultValueParser.GetDefaultValueIfAny(_reader, _property.DefaultValue, PropertyType, CustomAttributes, raw, out defaultValue); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs similarity index 96% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs index 440eb9487952d..32fb5ffa92644 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/PropertyInfos/RuntimePropertyInfo.cs @@ -123,7 +123,7 @@ public sealed override MethodInfo GetMethod public sealed override Type[] GetRequiredCustomModifiers() => PropertyTypeHandle.GetCustomModifiers(ContextTypeInfo.TypeContext, optional: false); - public sealed override object? GetValue(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? index, CultureInfo culture) + public sealed override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { if (_lazyGetterInvoker == null) { @@ -186,7 +186,7 @@ public sealed override MethodInfo SetMethod } } - public sealed override void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, object?[]? index, CultureInfo culture) + public sealed override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { if (_lazySetterInvoker == null) { @@ -195,10 +195,10 @@ public sealed override void SetValue(object? obj, object? value, BindingFlags in _lazySetterInvoker = Setter.GetUncachedMethodInvoker(Array.Empty(), this); } - object?[] arguments; + object[] arguments; if (index == null) { - arguments = new object?[] { value }; + arguments = new object[] { value }; } else { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs similarity index 96% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs index b4789f8af68d1..4144e4ae4d9fa 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs @@ -58,7 +58,7 @@ protected sealed override int InternalGetHashCode() protected MetadataReader Reader { get; } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string InternalGetNameIfAvailable(ref Type rootCauseForFailure) { if (_genericParameter.Name.IsNull(Reader)) return string.Empty; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.UnificationKey.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.UnificationKey.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.UnificationKey.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.UnificationKey.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForMethods.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.UnificationKey.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.UnificationKey.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.UnificationKey.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.UnificationKey.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfoForTypes.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.UnificationKey.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.UnificationKey.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.UnificationKey.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.UnificationKey.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs index 18c175185421f..80b394decba94 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeNamedTypeInfo.cs @@ -106,7 +106,7 @@ public sealed override int MetadataToken public sealed override string ToString() { - StringBuilder? sb = null; + StringBuilder sb = null; foreach (GenericParameterHandle genericParameterHandle in _typeDefinition.GenericParameters) { @@ -148,7 +148,7 @@ internal sealed override Type InternalDeclaringType { get { - RuntimeTypeInfo? declaringType = null; + RuntimeTypeInfo declaringType = null; TypeDefinitionHandle enclosingTypeDefHandle = _typeDefinition.EnclosingType; if (!enclosingTypeDefHandle.IsNull(_reader)) { @@ -168,7 +168,7 @@ internal sealed override string InternalFullNameOfAssembly } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string InternalGetNameIfAvailable(ref Type rootCauseForFailure) { ConstantStringValueHandle nameHandle = _typeDefinition.Name; string name = nameHandle.GetString(_reader); @@ -271,10 +271,10 @@ internal PropertyHandleCollection DeclaredPropertyHandles } } - public bool Equals(NativeFormatRuntimeNamedTypeInfo? other) + public bool Equals(NativeFormatRuntimeNamedTypeInfo other) { // RuntimeTypeInfo.Equals(object) is the one that encapsulates our unification strategy so defer to him. - object? otherAsObject = other; + object otherAsObject = other; return base.Equals(otherAsObject); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeTypeInfo.CoreGetDeclared.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeTypeInfo.CoreGetDeclared.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeTypeInfo.CoreGetDeclared.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeTypeInfo.CoreGetDeclared.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeArrayTypeInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs index 1e560f7f6991d..c6835e724ef94 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeBlockedTypeInfo.cs @@ -56,7 +56,7 @@ public sealed override IEnumerable CustomAttributes { get { - return Array.Empty(); + return Empty.Enumerable; } } @@ -172,7 +172,7 @@ internal sealed override Type InternalDeclaringType } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string InternalGetNameIfAvailable(ref Type rootCauseForFailure) { return GeneratedName; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeByRefTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeByRefTypeInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeByRefTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeByRefTypeInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.UnificationKey.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.UnificationKey.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.UnificationKey.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.UnificationKey.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs similarity index 95% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs index 1c767450be996..0e6fda3edaa72 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeClsIdTypeInfo.cs @@ -28,7 +28,7 @@ private RuntimeCLSIDTypeInfo(Guid clsid, string server) public sealed override bool ContainsGenericParameters => false; public sealed override string FullName => BaseType.FullName; public sealed override Guid GUID => _key.ClsId; - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) => BaseType.InternalGetNameIfAvailable(ref rootCauseForFailure); + public sealed override string InternalGetNameIfAvailable(ref Type rootCauseForFailure) => BaseType.InternalGetNameIfAvailable(ref rootCauseForFailure); public sealed override bool IsGenericTypeDefinition => false; public sealed override int MetadataToken => BaseType.MetadataToken; public sealed override string Namespace => BaseType.Namespace; @@ -39,7 +39,7 @@ public sealed override IEnumerable CustomAttributes { get { - return Array.Empty(); + return Empty.Enumerable; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.UnificationKey.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.UnificationKey.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.UnificationKey.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.UnificationKey.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs index a2a010de909ce..5cd6c23e8ca3a 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeConstructedGenericTypeInfo.cs @@ -172,7 +172,7 @@ public sealed override string ToString() { // Get the FullName of the generic type definition in a pay-for-play safe way. RuntimeTypeInfo genericTypeDefinition = GenericTypeDefinitionTypeInfo; - string? genericTypeDefinitionString = null; + string genericTypeDefinitionString = null; if (genericTypeDefinition.InternalNameIfAvailable != null) // Want to avoid "cry-wolf" exceptions: if we can't even get the simple name, don't bother getting the FullName. { // Given our current pay for play policy, it should now be safe to attempt getting the FullName. (But guard with a try-catch in case this assumption is wrong.) @@ -259,7 +259,7 @@ internal sealed override string InternalFullNameOfAssembly } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string InternalGetNameIfAvailable(ref Type rootCauseForFailure) { return GenericTypeDefinitionTypeInfo.InternalGetNameIfAvailable(ref rootCauseForFailure); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeGenericParameterTypeInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.UnificationKey.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.UnificationKey.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.UnificationKey.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.UnificationKey.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs similarity index 95% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs index 67fe290b14997..05a65a8c80a97 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeHasElementTypeInfo.cs @@ -77,7 +77,7 @@ public sealed override IEnumerable CustomAttributes { get { - return Array.Empty(); + return Empty.Enumerable; } } @@ -162,9 +162,9 @@ internal sealed override Type InternalDeclaringType } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string InternalGetNameIfAvailable(ref Type rootCauseForFailure) { - string? elementTypeName = _key.ElementType.InternalGetNameIfAvailable(ref rootCauseForFailure); + string elementTypeName = _key.ElementType.InternalGetNameIfAvailable(ref rootCauseForFailure); if (elementTypeName == null) { rootCauseForFailure = _key.ElementType; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs similarity index 96% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs index ff70df743ffd2..ddf99822a3ff3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNamedTypeInfo.cs @@ -47,10 +47,10 @@ public sealed override IEnumerable CustomAttributes } } - public bool Equals(RuntimeNamedTypeInfo? other) + public bool Equals(RuntimeNamedTypeInfo other) { // RuntimeTypeInfo.Equals(object) is the one that encapsulates our unification strategy so defer to him. - object? otherAsObject = other; + object otherAsObject = other; return base.Equals(otherAsObject); } @@ -93,10 +93,10 @@ public sealed override string FullName string name = Name; - Type? declaringType = this.DeclaringType; - if (declaringType is not null) + Type declaringType = this.DeclaringType; + if (declaringType != null) { - string? declaringTypeFullName = declaringType.FullName; + string declaringTypeFullName = declaringType.FullName; return declaringTypeFullName + "+" + name; } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs similarity index 98% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs index 7176f4901bc6b..2939a881e75d2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeNoMetadataNamedTypeInfo.cs @@ -152,7 +152,7 @@ internal sealed override Type InternalDeclaringType } } - internal sealed override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure) + public sealed override string InternalGetNameIfAvailable(ref Type rootCauseForFailure) { rootCauseForFailure = this; return null; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimePointerTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimePointerTypeInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimePointerTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimePointerTypeInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeDefinitionTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeDefinitionTypeInfo.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeDefinitionTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeDefinitionTypeInfo.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs similarity index 96% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs index d97fada651f20..0fd1fccfc3574 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.CoreGetDeclared.cs @@ -38,7 +38,7 @@ internal IEnumerable CoreGetDeclaredConstructors(NameFilter opt if (definingType != null) { // If there is a definingType, we do not support Synthetic constructors - Debug.Assert(object.ReferenceEquals(SyntheticConstructors, Array.Empty())); + Debug.Assert(object.ReferenceEquals(SyntheticConstructors, Empty.Enumerable)); return definingType.CoreGetDeclaredConstructors(optionalNameFilter, this); } @@ -61,7 +61,7 @@ internal IEnumerable CoreGetDeclaredMethods(NameFilter optionalNameF if (definingType != null) { // If there is a definingType, we do not support Synthetic constructors - Debug.Assert(object.ReferenceEquals(SyntheticMethods, Array.Empty())); + Debug.Assert(object.ReferenceEquals(SyntheticMethods, Empty.Enumerable)); return definingType.CoreGetDeclaredMethods(optionalNameFilter, reflectedType, this); } @@ -85,7 +85,7 @@ internal IEnumerable CoreGetDeclaredEvents(NameFilter optionalNameFil { return definingType.CoreGetDeclaredEvents(optionalNameFilter, reflectedType, this); } - return Array.Empty(); + return Empty.Enumerable; } internal IEnumerable CoreGetDeclaredFields(NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) @@ -95,7 +95,7 @@ internal IEnumerable CoreGetDeclaredFields(NameFilter optionalNameFil { return definingType.CoreGetDeclaredFields(optionalNameFilter, reflectedType, this); } - return Array.Empty(); + return Empty.Enumerable; } internal IEnumerable CoreGetDeclaredProperties(NameFilter optionalNameFilter, RuntimeTypeInfo reflectedType) @@ -106,7 +106,7 @@ internal IEnumerable CoreGetDeclaredProperties(NameFilter optional return definingType.CoreGetDeclaredProperties(optionalNameFilter, reflectedType, this); } - return Array.Empty(); + return Empty.Enumerable; } // diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.GetMember.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.GetMember.cs similarity index 84% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.GetMember.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.GetMember.cs index 832d741bbb774..439343d33027b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.GetMember.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.GetMember.cs @@ -32,9 +32,9 @@ public sealed override MemberInfo[] GetMember(string name, MemberTypes type, Bin private MemberInfo[] GetMemberImpl(string optionalNameOrPrefix, MemberTypes type, BindingFlags bindingAttr) { bool prefixSearch = optionalNameOrPrefix != null && optionalNameOrPrefix.EndsWith("*", StringComparison.Ordinal); - string? optionalName = prefixSearch ? null : optionalNameOrPrefix; + string optionalName = prefixSearch ? null : optionalNameOrPrefix; - Func? predicate = null; + Func predicate = null; if (prefixSearch) { bool ignoreCase = (bindingAttr & BindingFlags.IgnoreCase) != 0; @@ -160,5 +160,20 @@ private MemberInfo GetDeclaredMemberWithSameMetadataDefinitionAs(MemberInfo memb } return null; } + + // DynamicallyAccessedMemberTypes.All keeps more data than what a member can use: + // - Keeps info about interfaces + // - Complete Nested types (nested type body and all its members including other nested types) + // - Public and private base type information + // Instead, the GetAllMembers constant will keep: + // - The nested types body but not the members + // - Base type public information but not private information. This information should not + // be visible via the derived type and is ignored by reflection + internal const DynamicallyAccessedMemberTypes GetAllMembers = DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields | + DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods | + DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents | + DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties | + DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | + DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs similarity index 90% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs index aa845932759a3..77dccda7966be 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.InvokeMember.cs @@ -12,9 +12,9 @@ namespace System.Reflection.Runtime.TypeInfos internal abstract partial class RuntimeTypeInfo { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] - public sealed override object? InvokeMember( - string name, BindingFlags bindingFlags, Binder? binder, object? target, - object?[]? providedArgs, ParameterModifier[]? modifiers, CultureInfo? culture, string[]? namedParams) + public sealed override object InvokeMember( + string name, BindingFlags bindingFlags, Binder binder, object target, + object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParams) { const BindingFlags MemberBindingMask = (BindingFlags)0x000000FF; const BindingFlags InvocationMask = (BindingFlags)0x0000FF00; @@ -60,7 +60,7 @@ internal abstract partial class RuntimeTypeInfo #region COM Interop if (target != null && target.GetType().IsCOMObject) - throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); + throw new PlatformNotSupportedException(SR.Arg_PlatformNotSupportedInvokeMemberCom); #endregion #region Check that any named paramters are not null @@ -98,8 +98,13 @@ internal abstract partial class RuntimeTypeInfo if (name.Length == 0 || name.Equals(@"[DISPID=0]")) { - // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString - name = GetDefaultMemberName() ?? "ToString"; + name = GetDefaultMemberName(); + + if (name == null) + { + // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString + name = "ToString"; + } } #endregion @@ -138,8 +143,10 @@ internal abstract partial class RuntimeTypeInfo #endregion #region Lookup Field - FieldInfo? selFld = null; - FieldInfo[] flds = (FieldInfo[])GetMember(name, MemberTypes.Field, bindingFlags); + FieldInfo selFld = null; + FieldInfo[] flds = GetMember(name, MemberTypes.Field, bindingFlags) as FieldInfo[]; + + Debug.Assert(flds != null); if (flds.Length == 1) { @@ -170,15 +177,13 @@ internal abstract partial class RuntimeTypeInfo if (idxCnt > 0) { - Debug.Assert(providedArgs != null); - // Verify that all of the index values are ints int[] idx = new int[idxCnt]; for (int i = 0; i < idxCnt; i++) { try { - idx[i] = ((IConvertible)providedArgs[i]!).ToInt32(null); + idx[i] = ((IConvertible)providedArgs[i]).ToInt32(null); } catch (InvalidCastException) { @@ -187,7 +192,7 @@ internal abstract partial class RuntimeTypeInfo } // Set or get the value... - Array a = (Array)selFld.GetValue(target)!; + Array a = (Array)selFld.GetValue(target); // Set or get the value in the array if ((bindingFlags & BindingFlags.GetField) != 0) @@ -259,15 +264,15 @@ internal abstract partial class RuntimeTypeInfo } #endregion - MethodInfo[]? finalists = null; - MethodInfo? finalist = null; + MethodInfo[] finalists = null; + MethodInfo finalist = null; #region BindingFlags.InvokeMethod if ((bindingFlags & BindingFlags.InvokeMethod) != 0) { #region Lookup Methods - MethodInfo[] semiFinalists = (MethodInfo[])GetMember(name, MemberTypes.Method, bindingFlags); - LowLevelListWithIList? results = null; + MethodInfo[] semiFinalists = GetMember(name, MemberTypes.Method, bindingFlags) as MethodInfo[]; + LowLevelListWithIList results = null; for (int i = 0; i < semiFinalists.Length; i++) { @@ -309,12 +314,12 @@ internal abstract partial class RuntimeTypeInfo if (finalist == null && isGetProperty || isSetProperty) { #region Lookup Property - PropertyInfo[] semiFinalists = (PropertyInfo[])GetMember(name, MemberTypes.Property, bindingFlags); - LowLevelListWithIList? results = null; + PropertyInfo[] semiFinalists = GetMember(name, MemberTypes.Property, bindingFlags) as PropertyInfo[]; + LowLevelListWithIList results = null; for (int i = 0; i < semiFinalists.Length; i++) { - MethodInfo? semiFinalist; + MethodInfo semiFinalist; if (isSetProperty) { @@ -381,10 +386,10 @@ internal abstract partial class RuntimeTypeInfo if (providedArgs == null) providedArgs = Array.Empty(); - object? state = null; + object state = null; - MethodBase? invokeMethod = null; + MethodBase invokeMethod = null; try { invokeMethod = binder.BindToMethod(bindingFlags, finalists, ref providedArgs, modifiers, culture, namedParams, out state); } catch (MissingMethodException) { } @@ -395,7 +400,7 @@ internal abstract partial class RuntimeTypeInfo //if (useCache && argCnt == invokeMethod.GetParameters().Length) // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, invokeMethod); - object? result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture); + object result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture); if (state != null) binder.ReorderArgumentArray(ref providedArgs, state); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.TypeComponentsCache.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs similarity index 97% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs index c52da3fb06481..647b50e484a93 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.cs @@ -183,7 +183,7 @@ public sealed override Type[] GenericTypeArguments | DynamicallyAccessedMemberTypes.PublicNestedTypes)] public sealed override MemberInfo[] GetDefaultMembers() { - string? defaultMemberName = GetDefaultMemberName(); + string defaultMemberName = GetDefaultMemberName(); return defaultMemberName != null ? GetMember(defaultMemberName) : Array.Empty(); } @@ -450,10 +450,10 @@ public sealed override Type MakeGenericType(params Type[] typeArguments) // the Type object for an inconsistent generic type - no MethodTable will ever match it so any attempt to "invoke" it // will throw an exception. bool foundSignatureType = false; - RuntimeTypeInfo?[] runtimeTypeArguments = new RuntimeTypeInfo[typeArguments.Length]; + RuntimeTypeInfo[] runtimeTypeArguments = new RuntimeTypeInfo[typeArguments.Length]; for (int i = 0; i < typeArguments.Length; i++) { - RuntimeTypeInfo? runtimeTypeArgument = runtimeTypeArguments[i] = typeArguments[i] as RuntimeTypeInfo; + RuntimeTypeInfo runtimeTypeArgument = runtimeTypeArguments[i] = typeArguments[i] as RuntimeTypeInfo; if (runtimeTypeArgument == null) { if (typeArguments[i] == null) @@ -465,7 +465,7 @@ public sealed override Type MakeGenericType(params Type[] typeArguments) } else { - throw new PlatformNotSupportedException(SR.Format(SR.Reflection_CustomReflectionObjectsNotSupported, typeArguments[i])); + throw new PlatformNotSupportedException(SR.PlatformNotSupported_MakeGenericType); // "PlatformNotSupported" because on desktop, passing in a foreign type is allowed and creates a RefEmit.TypeBuilder } } } @@ -475,7 +475,7 @@ public sealed override Type MakeGenericType(params Type[] typeArguments) for (int i = 0; i < typeArguments.Length; i++) { - RuntimeTypeInfo runtimeTypeArgument = runtimeTypeArguments[i]!; + RuntimeTypeInfo runtimeTypeArgument = runtimeTypeArguments[i]; // Desktop compatibility: Treat generic type definitions as a constructed generic type using the generic parameters as type arguments. if (runtimeTypeArgument.IsGenericTypeDefinition) @@ -485,7 +485,7 @@ public sealed override Type MakeGenericType(params Type[] typeArguments) throw new TypeLoadException(SR.CannotUseByRefLikeTypeInInstantiation); } - return this.GetConstructedGenericTypeWithTypeHandle(runtimeTypeArguments!); + return this.GetConstructedGenericTypeWithTypeHandle(runtimeTypeArguments); } public sealed override Type MakePointerType() @@ -505,8 +505,8 @@ public sealed override string Name { get { - Type? rootCauseForFailure = null; - string? name = InternalGetNameIfAvailable(ref rootCauseForFailure); + Type rootCauseForFailure = null; + string name = InternalGetNameIfAvailable(ref rootCauseForFailure); if (name == null) throw ReflectionCoreExecution.ExecutionDomain.CreateMissingMetadataException(rootCauseForFailure); return name; @@ -614,7 +614,7 @@ internal virtual RuntimeNamedTypeInfo AnchoringTypeDefinitionForDeclaredMembers // internal abstract string InternalFullNameOfAssembly { get; } - internal abstract override string? InternalGetNameIfAvailable(ref Type? rootCauseForFailure); + public abstract override string InternalGetNameIfAvailable(ref Type rootCauseForFailure); // // Left unsealed as HasElement types must override this. @@ -674,7 +674,7 @@ internal virtual IEnumerable SyntheticConstructors { get { - return Array.Empty(); + return Empty.Enumerable; } } @@ -685,7 +685,7 @@ internal virtual IEnumerable SyntheticMethods { get { - return Array.Empty(); + return Empty.Enumerable; } } @@ -776,7 +776,7 @@ internal virtual Type BaseTypeWithoutTheGenericParameterQuirk get { QTypeDefRefOrSpec baseTypeDefRefOrSpec = TypeRefDefOrSpecForBaseType; - RuntimeTypeInfo? baseType = null; + RuntimeTypeInfo baseType = null; if (!baseTypeDefRefOrSpec.IsValid) { baseType = baseTypeDefRefOrSpec.Resolve(this.TypeContext); @@ -785,10 +785,10 @@ internal virtual Type BaseTypeWithoutTheGenericParameterQuirk } } - private string? GetDefaultMemberName() + private string GetDefaultMemberName() { Type defaultMemberAttributeType = typeof(DefaultMemberAttribute); - for (Type type = this; type != null; type = type.BaseType!) + for (Type type = this; type != null; type = type.BaseType) { foreach (CustomAttributeData attribute in type.CustomAttributes) { @@ -800,7 +800,7 @@ internal virtual Type BaseTypeWithoutTheGenericParameterQuirk // constructor. Debug.Assert(attribute.ConstructorArguments.Count == 1 && attribute.ConstructorArguments[0].Value is string); - string? memberName = (string?)(attribute.ConstructorArguments[0].Value); + string memberName = (string)(attribute.ConstructorArguments[0].Value); return memberName; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/GetTypeOptions.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/GetTypeOptions.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/GetTypeOptions.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/GetTypeOptions.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs similarity index 100% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeLexer.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeName.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeName.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeName.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeName.cs index f4628ac0998c2..91fcf3981c4b2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeName.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeName.cs @@ -133,7 +133,7 @@ public sealed override Type ResolveType(Assembly containingAssemblyIfAny, GetTyp // Don't change these flags - we may be talking to a third party type here and we need to invoke it the way CoreClr does. BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic; - Type? nestedType; + Type nestedType; if (!getTypeOptions.IgnoreCase) { nestedType = declaringType.GetNestedType(_nestedTypeName, bf); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs rename to src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs index d51157cc5b41d..507069941763b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeParsing/TypeParser.cs @@ -198,7 +198,7 @@ private TypeName ParseGenericTypeArgument() } else if (token == TokenType.OpenSqBracket) { - RuntimeAssemblyName? assemblyName = null; + RuntimeAssemblyName assemblyName = null; NonQualifiedTypeName typeName = ParseNonQualifiedTypeName(); token = _lexer.GetNextToken(); if (token == TokenType.Comma) diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 7bbc2de4e88f1..4b867227bf3c9 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -105,7 +105,7 @@ private static unsafe bool TryGetNativeReaderForBlob(NativeFormatModuleInfo modu /// /// Runtime handle of the type in question /// TypeDef handle for the type - public sealed override unsafe bool TryGetMetadataForNamedType(RuntimeTypeHandle runtimeTypeHandle, out QTypeDefinition qTypeDefinition) + public sealed unsafe override bool TryGetMetadataForNamedType(RuntimeTypeHandle runtimeTypeHandle, out QTypeDefinition qTypeDefinition) { Debug.Assert(!RuntimeAugments.IsGenericType(runtimeTypeHandle)); return TypeLoaderEnvironment.Instance.TryGetMetadataForNamedType(runtimeTypeHandle, out qTypeDefinition); @@ -117,7 +117,7 @@ public sealed override unsafe bool TryGetMetadataForNamedType(RuntimeTypeHandle // Preconditions: // runtimeTypeHandle is a typedef or a generic type instance (not a constructed type such as an array) // - public sealed override unsafe bool IsReflectionBlocked(RuntimeTypeHandle runtimeTypeHandle) + public sealed unsafe override bool IsReflectionBlocked(RuntimeTypeHandle runtimeTypeHandle) { // For generic types, use the generic type definition runtimeTypeHandle = GetTypeDefinition(runtimeTypeHandle); @@ -165,7 +165,7 @@ public sealed override unsafe bool IsReflectionBlocked(RuntimeTypeHandle runtime /// /// TypeDef handle for the type to look up /// Runtime type handle (MethodTable) for the given type - public sealed override unsafe bool TryGetNamedTypeForMetadata(QTypeDefinition qTypeDefinition, out RuntimeTypeHandle runtimeTypeHandle) + public sealed unsafe override bool TryGetNamedTypeForMetadata(QTypeDefinition qTypeDefinition, out RuntimeTypeHandle runtimeTypeHandle) { return TypeLoaderEnvironment.Instance.TryGetOrCreateNamedTypeForMetadata(qTypeDefinition, out runtimeTypeHandle); } @@ -182,7 +182,7 @@ public sealed override unsafe bool TryGetNamedTypeForMetadata(QTypeDefinition qT /// MethodTable of the type in question /// Metadata reader for the type /// Located TypeRef handle - public sealed override unsafe bool TryGetTypeReferenceForNamedType(RuntimeTypeHandle runtimeTypeHandle, out MetadataReader metadataReader, out TypeReferenceHandle typeRefHandle) + public sealed unsafe override bool TryGetTypeReferenceForNamedType(RuntimeTypeHandle runtimeTypeHandle, out MetadataReader metadataReader, out TypeReferenceHandle typeRefHandle) { return TypeLoaderEnvironment.TryGetTypeReferenceForNamedType(runtimeTypeHandle, out metadataReader, out typeRefHandle); } @@ -205,7 +205,7 @@ public sealed override unsafe bool TryGetTypeReferenceForNamedType(RuntimeTypeHa /// Metadata reader for module containing the type reference /// TypeRef handle to look up /// Resolved MethodTable for the type reference - public sealed override unsafe bool TryGetNamedTypeForTypeReference(MetadataReader metadataReader, TypeReferenceHandle typeRefHandle, out RuntimeTypeHandle runtimeTypeHandle) + public sealed unsafe override bool TryGetNamedTypeForTypeReference(MetadataReader metadataReader, TypeReferenceHandle typeRefHandle, out RuntimeTypeHandle runtimeTypeHandle) { return TypeLoaderEnvironment.TryGetNamedTypeForTypeReference(metadataReader, typeRefHandle, out runtimeTypeHandle); } @@ -219,7 +219,7 @@ public sealed override unsafe bool TryGetNamedTypeForTypeReference(MetadataReade // // This is not equivalent to calling TryGetMultiDimTypeForElementType() with a rank of 1! // - public sealed override unsafe bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, out RuntimeTypeHandle arrayTypeHandle) + public sealed unsafe override bool TryGetArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, out RuntimeTypeHandle arrayTypeHandle) { if (RuntimeAugments.IsGenericTypeDefinition(elementTypeHandle)) { @@ -240,7 +240,7 @@ public sealed override unsafe bool TryGetArrayTypeForElementType(RuntimeTypeHand // // This is not equivalent to calling TryGetMultiDimTypeElementType() with a rank of 1! // - public sealed override unsafe bool TryGetArrayTypeElementType(RuntimeTypeHandle arrayTypeHandle, out RuntimeTypeHandle elementTypeHandle) + public sealed unsafe override bool TryGetArrayTypeElementType(RuntimeTypeHandle arrayTypeHandle, out RuntimeTypeHandle elementTypeHandle) { elementTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(arrayTypeHandle); return true; @@ -256,7 +256,7 @@ public sealed override unsafe bool TryGetArrayTypeElementType(RuntimeTypeHandle // // Calling this with rank 1 is not equivalent to calling TryGetArrayTypeForElementType()! // - public sealed override unsafe bool TryGetMultiDimArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, int rank, out RuntimeTypeHandle arrayTypeHandle) + public sealed unsafe override bool TryGetMultiDimArrayTypeForElementType(RuntimeTypeHandle elementTypeHandle, int rank, out RuntimeTypeHandle arrayTypeHandle) { if (RuntimeAugments.IsGenericTypeDefinition(elementTypeHandle)) { @@ -279,7 +279,7 @@ public sealed override unsafe bool TryGetMultiDimArrayTypeForElementType(Runtime // Preconditions: // targetTypeHandle is a valid RuntimeTypeHandle. // - public sealed override unsafe bool TryGetPointerTypeForTargetType(RuntimeTypeHandle targetTypeHandle, out RuntimeTypeHandle pointerTypeHandle) + public sealed unsafe override bool TryGetPointerTypeForTargetType(RuntimeTypeHandle targetTypeHandle, out RuntimeTypeHandle pointerTypeHandle) { return TypeLoaderEnvironment.Instance.TryGetPointerTypeForTargetType(targetTypeHandle, out pointerTypeHandle); } @@ -291,7 +291,7 @@ public sealed override unsafe bool TryGetPointerTypeForTargetType(RuntimeTypeHan // Preconditions: // pointerTypeHandle is a valid RuntimeTypeHandle of type pointer. // - public sealed override unsafe bool TryGetPointerTypeTargetType(RuntimeTypeHandle pointerTypeHandle, out RuntimeTypeHandle targetTypeHandle) + public sealed unsafe override bool TryGetPointerTypeTargetType(RuntimeTypeHandle pointerTypeHandle, out RuntimeTypeHandle targetTypeHandle) { targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(pointerTypeHandle); return true; @@ -304,7 +304,7 @@ public sealed override unsafe bool TryGetPointerTypeTargetType(RuntimeTypeHandle // Preconditions: // targetTypeHandle is a valid RuntimeTypeHandle. // - public sealed override unsafe bool TryGetByRefTypeForTargetType(RuntimeTypeHandle targetTypeHandle, out RuntimeTypeHandle byRefTypeHandle) + public sealed unsafe override bool TryGetByRefTypeForTargetType(RuntimeTypeHandle targetTypeHandle, out RuntimeTypeHandle byRefTypeHandle) { return TypeLoaderEnvironment.Instance.TryGetByRefTypeForTargetType(targetTypeHandle, out byRefTypeHandle); } @@ -316,7 +316,7 @@ public sealed override unsafe bool TryGetByRefTypeForTargetType(RuntimeTypeHandl // Preconditions: // byRefTypeHandle is a valid RuntimeTypeHandle of a byref. // - public sealed override unsafe bool TryGetByRefTypeTargetType(RuntimeTypeHandle byRefTypeHandle, out RuntimeTypeHandle targetTypeHandle) + public sealed unsafe override bool TryGetByRefTypeTargetType(RuntimeTypeHandle byRefTypeHandle, out RuntimeTypeHandle targetTypeHandle) { targetTypeHandle = RuntimeAugments.GetRelatedParameterTypeHandle(byRefTypeHandle); return true; @@ -330,7 +330,7 @@ public sealed override unsafe bool TryGetByRefTypeTargetType(RuntimeTypeHandle b // runtimeTypeDefinitionHandle is a valid RuntimeTypeHandle for a generic type. // genericTypeArgumentHandles is an array of valid RuntimeTypeHandles. // - public sealed override unsafe bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle) + public sealed unsafe override bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle) { if (TypeLoaderEnvironment.Instance.TryLookupConstructedGenericTypeForComponents(genericTypeDefinitionHandle, genericTypeArgumentHandles, out runtimeTypeHandle)) { @@ -1400,7 +1400,7 @@ private static unsafe bool TryGetMethodForOriginalLdFtnResult_GenericMethodWithI // // This resolves RuntimeMethodHandles for methods declared on non-generic types (declaringTypeHandle is an output of this method.) // - public sealed override unsafe bool TryGetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) + public sealed unsafe override bool TryGetMethodFromHandle(RuntimeMethodHandle runtimeMethodHandle, out RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles) { MethodNameAndSignature nameAndSignature; methodHandle = default(QMethodDefinition); @@ -1421,7 +1421,7 @@ public sealed override bool TryGetMethodFromHandleAndType(RuntimeMethodHandle ru // // This resolves RuntimeFieldHandles for fields declared on non-generic types (declaringTypeHandle is an output of this method.) // - public sealed override unsafe bool TryGetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle) + public sealed unsafe override bool TryGetFieldFromHandle(RuntimeFieldHandle runtimeFieldHandle, out RuntimeTypeHandle declaringTypeHandle, out FieldHandle fieldHandle) { fieldHandle = default(FieldHandle); diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/PointerTypeFieldAccessorForStaticFields.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/PointerTypeFieldAccessorForStaticFields.cs index 224ad076cbce7..a951827597362 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/PointerTypeFieldAccessorForStaticFields.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/PointerTypeFieldAccessorForStaticFields.cs @@ -16,7 +16,7 @@ public PointerTypeFieldAccessorForStaticFields(IntPtr cctorContext, IntPtr stati { } - protected sealed override unsafe object GetFieldBypassCctor() + protected sealed unsafe override object GetFieldBypassCctor() { if (FieldBase == FieldTableFlags.GCStatic) { @@ -33,7 +33,7 @@ protected sealed override unsafe object GetFieldBypassCctor() return RuntimeAugments.LoadPointerTypeField(threadStaticRegion, FieldOffset, FieldTypeHandle); } - protected sealed override unsafe void UncheckedSetFieldBypassCctor(object value) + protected sealed unsafe override void UncheckedSetFieldBypassCctor(object value) { if (FieldBase == FieldTableFlags.GCStatic) { diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ReferenceTypeFieldAccessorForStaticFields.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ReferenceTypeFieldAccessorForStaticFields.cs index 5233fe28d5dab..ad9a193e860e1 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ReferenceTypeFieldAccessorForStaticFields.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ReferenceTypeFieldAccessorForStaticFields.cs @@ -16,7 +16,7 @@ public ReferenceTypeFieldAccessorForStaticFields(IntPtr cctorContext, IntPtr sta { } - protected sealed override unsafe object GetFieldBypassCctor() + protected sealed unsafe override object GetFieldBypassCctor() { if (FieldBase == FieldTableFlags.GCStatic) { @@ -33,7 +33,7 @@ protected sealed override unsafe object GetFieldBypassCctor() return RuntimeAugments.LoadReferenceTypeField(threadStaticRegion, FieldOffset); } - protected sealed override unsafe void UncheckedSetFieldBypassCctor(object value) + protected sealed unsafe override void UncheckedSetFieldBypassCctor(object value) { if (FieldBase == FieldTableFlags.GCStatic) { diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ValueTypeFieldAccessorForStaticFields.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ValueTypeFieldAccessorForStaticFields.cs index 28765e89600db..ae90edc558c6d 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ValueTypeFieldAccessorForStaticFields.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/FieldAccessors/ValueTypeFieldAccessorForStaticFields.cs @@ -16,7 +16,7 @@ public ValueTypeFieldAccessorForStaticFields(IntPtr cctorContext, IntPtr statics { } - protected sealed override unsafe object GetFieldBypassCctor() + protected sealed unsafe override object GetFieldBypassCctor() { if (FieldBase == FieldTableFlags.GCStatic) { @@ -33,7 +33,7 @@ protected sealed override unsafe object GetFieldBypassCctor() return RuntimeAugments.LoadValueTypeField(threadStaticRegion, FieldOffset, FieldTypeHandle); } - protected sealed override unsafe void UncheckedSetFieldBypassCctor(object value) + protected sealed unsafe override void UncheckedSetFieldBypassCctor(object value) { if (FieldBase == FieldTableFlags.GCStatic) { diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs index 46b245f9db743..db347ad0b787b 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/PayForPlayExperience/MissingMetadataExceptionCreator.cs @@ -15,17 +15,17 @@ namespace Internal.Reflection.Execution.PayForPlayExperience { public static class MissingMetadataExceptionCreator { - internal static MissingMetadataException Create(string resourceId, MemberInfo? pertainant) + internal static MissingMetadataException Create(string resourceId, MemberInfo pertainant) { return CreateFromMetadataObject(resourceId, pertainant); } - internal static MissingMetadataException Create(TypeInfo? pertainant) + internal static MissingMetadataException Create(TypeInfo pertainant) { return CreateFromMetadataObject(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant); } - internal static MissingMetadataException Create(TypeInfo? pertainant, string nestedTypeName) + internal static MissingMetadataException Create(TypeInfo pertainant, string nestedTypeName) { if (pertainant == null) return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); @@ -40,7 +40,7 @@ internal static MissingMetadataException Create(TypeInfo? pertainant, string nes } } - internal static MissingMetadataException Create(Type? pertainant) + internal static MissingMetadataException Create(Type pertainant) { return CreateFromMetadataObject(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant); } @@ -50,7 +50,7 @@ internal static MissingMetadataException Create(RuntimeTypeHandle pertainant) return CreateFromMetadataObject(SR.Reflection_InsufficientMetadata_EdbNeeded, pertainant); } - private static MissingMetadataException CreateFromString(string? pertainant) + private static MissingMetadataException CreateFromString(string pertainant) { if (pertainant == null) return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); @@ -71,7 +71,7 @@ internal static MissingMetadataException CreateMissingConstructedGenericTypeExce return CreateFromString(s); } - internal static MissingMetadataException CreateFromMetadataObject(string resourceId, object? pertainant) + internal static MissingMetadataException CreateFromMetadataObject(string resourceId, object pertainant) { if (pertainant == null) return new MissingMetadataException(SR.Format(SR.Reflection_InsufficientMetadata_NoHelpAvailable, "")); @@ -99,13 +99,16 @@ public static string ComputeUsefulPertainantIfPossible(object pertainant) return type.ToDisplayStringIfAvailable(null); } - if (pertainant is MemberInfo memberInfo) + if (pertainant is MemberInfo) { + MemberInfo memberInfo = (MemberInfo)pertainant; + StringBuilder friendlyName = new StringBuilder(memberInfo.DeclaringType.ToDisplayStringIfAvailable(null)); friendlyName.Append('.'); friendlyName.Append(memberInfo.Name); - if (pertainant is MethodBase method) + if (pertainant is MethodBase) { + MethodBase method = (MethodBase)pertainant; bool first; // write out generic parameters @@ -246,7 +249,7 @@ internal static string ToDisplayStringIfAvailable(this Type type, List gene { genericParameterOffsets.Add(s.Length); if (genericArgCount > 0) - s += ","; + s = s + ","; } s += "]"; } @@ -280,7 +283,7 @@ private static string CreateConstructedGenericTypeStringIfAvailable(Type generic // Similarly, if we found too few, add them at the end. while (genericTypeArguments.Length > genericParameterOffsets.Count) { - genericTypeDefinitionString += ","; + genericTypeDefinitionString = genericTypeDefinitionString + ","; genericParameterOffsets.Add(genericTypeDefinitionString.Length); } diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj index d7883b5f2ebe7..e8b65e31ca05f 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj @@ -2,6 +2,7 @@ + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/AssemblyBinder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs similarity index 92% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/AssemblyBinder.cs rename to src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs index f68d8407b2781..0a7bab62ea362 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Reflection/Core/AssemblyBinder.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs @@ -6,15 +6,12 @@ using System.Reflection; using Internal.Metadata.NativeFormat; using System.Reflection.Runtime.General; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace Internal.Reflection.Core { // Auto StructLayout used to suppress warning that order of fields is not guaranteed in partial structs [StructLayout(LayoutKind.Auto)] - [ReflectionBlocked] - [CLSCompliant(false)] public partial struct AssemblyBindResult { public MetadataReader Reader; @@ -28,8 +25,6 @@ public partial struct AssemblyBindResult // // If the binder cannot locate an assembly, it must return null and set "exception" to an exception object. // - [ReflectionBlocked] - [CLSCompliant(false)] public abstract class AssemblyBinder { public const string DefaultAssemblyNameForGetType = "System.Private.CoreLib"; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs index c16a125c3474e..f5bdf03faa20a 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs @@ -941,7 +941,7 @@ private static unsafe int CreateGCDesc(LowLevelList bitfield, int size, bo } else { - seriesSize -= size; + seriesSize = seriesSize - size; *ptr-- = (void*)seriesOffset; *ptr-- = (void*)seriesSize; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionary.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionary.cs index 56a7fd8aa6e96..eed0b97d01e92 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionary.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionary.cs @@ -59,7 +59,7 @@ public GenericMethodDictionary(GenericDictionaryCell[] cells) : base(cells) { } - public override unsafe IntPtr Allocate() + public unsafe override IntPtr Allocate() { Debug.Assert(_addressOfFirstCellSlot == IntPtr.Zero); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs index 69df4c61d68df..68b8ffcf9b3a0 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs @@ -23,7 +23,7 @@ public abstract class GenericDictionaryCell { internal abstract void Prepare(TypeBuilder builder); internal abstract IntPtr Create(TypeBuilder builder); - internal virtual unsafe void WriteCellIntoDictionary(TypeBuilder typeBuilder, IntPtr* pDictionary, int slotIndex) + internal unsafe virtual void WriteCellIntoDictionary(TypeBuilder typeBuilder, IntPtr* pDictionary, int slotIndex) { pDictionary[slotIndex] = Create(typeBuilder); } @@ -57,7 +57,7 @@ internal override IntPtr Create(TypeBuilder builder) throw new NotSupportedException(); } - internal override unsafe void WriteCellIntoDictionary(TypeBuilder typeBuilder, IntPtr* pDictionary, int slotIndex) + internal unsafe override void WriteCellIntoDictionary(TypeBuilder typeBuilder, IntPtr* pDictionary, int slotIndex) { pDictionary[slotIndex] = new IntPtr(pDictionary + OtherDictionarySlot); } @@ -289,7 +289,7 @@ private class MethodDictionaryCell : GenericDictionaryCell { internal InstantiatedMethod GenericMethod; - internal override unsafe void Prepare(TypeBuilder builder) + internal unsafe override void Prepare(TypeBuilder builder) { if (GenericMethod.IsCanonicalMethod(CanonicalFormKind.Any)) Environment.FailFast("Method dictionaries of canonical methods do not exist"); @@ -312,7 +312,7 @@ private class FieldLdTokenCell : GenericDictionaryCell internal TypeDesc ContainingType; internal IntPtr FieldName; - internal override unsafe void Prepare(TypeBuilder builder) + internal unsafe override void Prepare(TypeBuilder builder) { if (ContainingType.IsCanonicalSubtype(CanonicalFormKind.Any)) Environment.FailFast("Ldtoken is not permitted for a canonical field"); @@ -336,7 +336,7 @@ private class MethodLdTokenCell : GenericDictionaryCell internal IntPtr MethodName; internal RuntimeSignature MethodSignature; - internal override unsafe void Prepare(TypeBuilder builder) + internal unsafe override void Prepare(TypeBuilder builder) { if (Method.IsCanonicalMethod(CanonicalFormKind.Any)) Environment.FailFast("Ldtoken is not permitted for a canonical method"); @@ -532,11 +532,11 @@ public static GenericDictionaryCell CreateIntPtrCell(IntPtr ptrValue) private class IntPtrCell : GenericDictionaryCell { internal IntPtr Value; - internal override unsafe void Prepare(TypeBuilder builder) + internal unsafe override void Prepare(TypeBuilder builder) { } - internal override unsafe IntPtr Create(TypeBuilder builder) + internal unsafe override IntPtr Create(TypeBuilder builder) { return Value; } @@ -567,7 +567,7 @@ private class MethodCell : GenericDictionaryCell private MethodDesc _methodToUseForInstantiatingParameters; private IntPtr _exactFunctionPointer; - internal override unsafe void Prepare(TypeBuilder builder) + internal unsafe override void Prepare(TypeBuilder builder) { _methodToUseForInstantiatingParameters = Method; @@ -761,7 +761,7 @@ private bool NeedsDictionaryParameterToCallCanonicalVersion(MethodDesc method) return Method.OwningType.IsValueType && !Method.UnboxingStub; } - internal override unsafe IntPtr Create(TypeBuilder builder) + internal unsafe override IntPtr Create(TypeBuilder builder) { if (_exactFunctionPointer != IntPtr.Zero) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.cs similarity index 96% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs rename to src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.cs index 35d240d925b3e..fa4cc68358574 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/MetadataReaderExtensions.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.cs @@ -2,20 +2,17 @@ // The .NET Foundation licenses this file to you under the MIT license. -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Runtime.CompilerServices; +using global::System; +using global::System.Reflection; +using global::System.Collections.Generic; -using Internal.Metadata.NativeFormat; +using global::Internal.Metadata.NativeFormat; using Debug = System.Diagnostics.Debug; using AssemblyFlags = Internal.Metadata.NativeFormat.AssemblyFlags; namespace System.Reflection.Runtime.General { - [ReflectionBlocked] - [CLSCompliant(false)] public static partial class MetadataReaderExtensions { /// diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs index efafe262ed4d5..f6e52ed013dd2 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ModuleList.cs @@ -710,7 +710,10 @@ public void RegisterNewModules(ModuleType moduleType) updatedModules[oldModuleCount + newModuleIndex] = newModuleInfo; - _moduleRegistrationCallbacks?.Invoke(newModuleInfo); + if (_moduleRegistrationCallbacks != null) + { + _moduleRegistrationCallbacks(newModuleInfo); + } } // Atomically update the module map @@ -731,7 +734,10 @@ public void RegisterModule(ModuleInfo newModuleInfo) Array.Copy(_loadedModuleMap.Modules, 0, updatedModules, 0, oldModuleCount); } updatedModules[oldModuleCount] = newModuleInfo; - _moduleRegistrationCallbacks?.Invoke(newModuleInfo); + if (_moduleRegistrationCallbacks != null) + { + _moduleRegistrationCallbacks(newModuleInfo); + } // Atomically update the module map _loadedModuleMap = new ModuleMap(updatedModules); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs index 72609631283c2..054a5ec9956db 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs @@ -19,7 +19,7 @@ internal class NativeLayoutFieldAlgorithm : FieldLayoutAlgorithm private NoMetadataFieldLayoutAlgorithm _noMetadataFieldLayoutAlgorithm = new NoMetadataFieldLayoutAlgorithm(); private const int InstanceAlignmentEntry = 4; - public override unsafe bool ComputeContainsGCPointers(DefType type) + public unsafe override bool ComputeContainsGCPointers(DefType type) { if (type.IsTemplateCanonical()) { @@ -430,7 +430,7 @@ internal void GetFieldSizeAlignment(TypeDesc fieldType, out LayoutInt size, out alignment = fieldDefType.InstanceFieldAlignment; } - public override unsafe ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type) + public unsafe override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type) { // Use this constant to make the code below more laconic const ValueTypeShapeCharacteristics NotHA = ValueTypeShapeCharacteristics.None; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldDesc.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldDesc.cs index b658f1dc49c3a..056cb26016ef4 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldDesc.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldDesc.cs @@ -39,8 +39,6 @@ public override TypeDesc FieldType } } - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() => null; - public override bool HasRva { get diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs index 482e4243b8c97..60ea543a3ff22 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs @@ -19,7 +19,7 @@ internal class NoMetadataFieldLayoutAlgorithm : FieldLayoutAlgorithm #endif private static NativeLayoutFieldAlgorithm s_nativeLayoutFieldAlgorithm = new NativeLayoutFieldAlgorithm(); - public override unsafe bool ComputeContainsGCPointers(DefType type) + public unsafe override bool ComputeContainsGCPointers(DefType type) { return type.RuntimeTypeHandle.ToEETypePtr()->HasGCPointers; } @@ -28,7 +28,7 @@ public override unsafe bool ComputeContainsGCPointers(DefType type) /// Reads the minimal information about type layout encoded in the /// MethodTable. That doesn't include field information. /// - public override unsafe ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind) + public unsafe override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind) { // If we need the field information, delegate to the native layout algorithm or metadata algorithm if (layoutKind != InstanceLayoutKind.TypeOnly) diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs index ab1bbfba737a4..9c1c186f66e86 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs @@ -88,7 +88,7 @@ public TypeBuilder() /// The StaticClassConstructionContext for a type is encoded in the negative space /// of the NonGCStatic fields of a type. /// - public static readonly unsafe int ClassConstructorOffset = -sizeof(System.Runtime.CompilerServices.StaticClassConstructionContext); + public static unsafe readonly int ClassConstructorOffset = -sizeof(System.Runtime.CompilerServices.StaticClassConstructionContext); private LowLevelList _typesThatNeedTypeHandles = new LowLevelList(); @@ -105,10 +105,6 @@ public TypeBuilder() // Helper exception to abort type building if we do not find the generic type template internal class MissingTemplateException : Exception { - public MissingTemplateException() - // Cannot afford calling into resource manager from here, even to get the default message for System.Exception. - // This exception is always caught and rethrown as something more user friendly. - : base("Template is missing") { } } @@ -266,8 +262,10 @@ internal void PrepareType(TypeDesc type) bool noExtraPreparation = false; // Set this to true for types which don't need other types to be prepared. I.e GenericTypeDefinitions - if (type is DefType typeAsDefType) + if (type is DefType) { + DefType typeAsDefType = (DefType)type; + if (typeAsDefType.HasInstantiation) { if (typeAsDefType.IsTypeDefinition) @@ -303,8 +301,10 @@ internal void PrepareType(TypeDesc type) { PrepareType(((ParameterizedType)type).ParameterType); - if (type is ArrayType typeAsArrayType) + if (type is ArrayType) { + ArrayType typeAsArrayType = (ArrayType)type; + if (typeAsArrayType.IsSzArray && !typeAsArrayType.ElementType.IsPointer) { TypeDesc.ComputeTemplate(state); @@ -1322,8 +1322,10 @@ private void FinishRuntimeType(TypeDesc type) var state = type.GetTypeBuilderState(); - if (type is DefType typeAsDefType) + if (type is DefType) { + DefType typeAsDefType = (DefType)type; + if (type.HasInstantiation) { // Type definitions don't need any further finishing once created by the EETypeCreator @@ -1361,8 +1363,10 @@ private void FinishRuntimeType(TypeDesc type) } else if (type is ParameterizedType) { - if (type is ArrayType typeAsSzArrayType) + if (type is ArrayType) { + ArrayType typeAsSzArrayType = (ArrayType)type; + state.HalfBakedRuntimeTypeHandle.SetRelatedParameterType(GetRuntimeTypeHandle(typeAsSzArrayType.ElementType)); state.HalfBakedRuntimeTypeHandle.SetComponentSize(state.ComponentSize.Value); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs index dcc81310178d8..85037bae3fa1e 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs @@ -973,8 +973,10 @@ public bool IsArrayOfReferenceTypes { return checked((ushort)((DefType)TypeBeingBuilt).InstanceFieldAlignment.AsInt); } - else if (TypeBeingBuilt is ArrayType arrayType) + else if (TypeBeingBuilt is ArrayType) { + ArrayType arrayType = (ArrayType)TypeBeingBuilt; + if (arrayType.ElementType is DefType) { return checked((ushort)((DefType)arrayType.ElementType).InstanceFieldAlignment.AsInt); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs index 5083a87002d38..1c1da35553b88 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs @@ -100,8 +100,9 @@ public RuntimeFieldHandleKey(RuntimeTypeHandle declaringType, string fieldName) public override bool Equals(object obj) { - if (obj is RuntimeFieldHandleKey other) + if (obj is RuntimeFieldHandleKey) { + RuntimeFieldHandleKey other = (RuntimeFieldHandleKey)obj; return Equals(other); } return false; @@ -144,8 +145,9 @@ public RuntimeMethodHandleKey(RuntimeTypeHandle declaringType, string methodName public override bool Equals(object obj) { - if (obj is RuntimeMethodHandleKey other) + if (obj is RuntimeMethodHandleKey) { + RuntimeMethodHandleKey other = (RuntimeMethodHandleKey)obj; return Equals(other); } return false; @@ -207,7 +209,7 @@ public unsafe RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeH fieldData->FieldName = fieldName; // Special flag (lowest bit set) in the handle value to indicate it was dynamically allocated - runtimeFieldHandleValue++; + runtimeFieldHandleValue = runtimeFieldHandleValue + 1; runtimeFieldHandle = *(RuntimeFieldHandle*)&runtimeFieldHandleValue; _runtimeFieldHandles.Add(key, runtimeFieldHandle); @@ -230,7 +232,7 @@ private unsafe bool TryGetDynamicRuntimeFieldHandleComponents(RuntimeFieldHandle // Special flag in the handle value to indicate it was dynamically allocated Debug.Assert((runtimeFieldHandleValue.ToInt64() & 0x1) == 0x1); - runtimeFieldHandleValue--; + runtimeFieldHandleValue = runtimeFieldHandleValue - 1; DynamicFieldHandleInfo* fieldData = (DynamicFieldHandleInfo*)runtimeFieldHandleValue.ToPointer(); declaringTypeHandle = *(RuntimeTypeHandle*)&(fieldData->DeclaringType); @@ -315,7 +317,7 @@ public unsafe RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTyp } // Special flag in the handle value to indicate it was dynamically allocated, and doesn't point into the InvokeMap blob - runtimeMethodHandleValue++; + runtimeMethodHandleValue = runtimeMethodHandleValue + 1; runtimeMethodHandle = * (RuntimeMethodHandle*)&runtimeMethodHandleValue; _runtimeMethodHandles.Add(key, runtimeMethodHandle); @@ -342,7 +344,7 @@ private unsafe bool TryGetDynamicRuntimeMethodHandleComponents(RuntimeMethodHand Debug.Assert((runtimeMethodHandleValue.ToInt64() & 0x1) == 0x1); // Special flag in the handle value to indicate it was dynamically allocated, and doesn't point into the InvokeMap blob - runtimeMethodHandleValue--; + runtimeMethodHandleValue = runtimeMethodHandleValue - 1; DynamicMethodHandleInfo* methodData = (DynamicMethodHandleInfo*)runtimeMethodHandleValue.ToPointer(); declaringTypeHandle = *(RuntimeTypeHandle*)&(methodData->DeclaringType); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs index 7c619907610f7..a0c3379a3efb0 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs @@ -417,7 +417,7 @@ public static unsafe IntPtr TryGetStaticClassConstructionContext(RuntimeTypeHand // what we have now is the base address of the non-gc statics of the type // what we need is the cctor context, which is just before that - ptr -= sizeof(System.Runtime.CompilerServices.StaticClassConstructionContext); + ptr = ptr - sizeof(System.Runtime.CompilerServices.StaticClassConstructionContext); return (IntPtr)ptr; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.NamedTypeLookup.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.NamedTypeLookup.cs index c8aec12bc11d8..478a6faa10511 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.NamedTypeLookup.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.NamedTypeLookup.cs @@ -41,7 +41,7 @@ private class NamedTypeLookupResult private class NamedTypeRuntimeTypeHandleToMetadataHashtable : LockFreeReaderHashtable { - protected override unsafe int GetKeyHashCode(RuntimeTypeHandle key) + protected unsafe override int GetKeyHashCode(RuntimeTypeHandle key) { return (int)key.ToEETypePtr()->HashCode; } @@ -50,7 +50,7 @@ protected override bool CompareKeyToValue(RuntimeTypeHandle key, NamedTypeLookup return key.Equals(value.RuntimeTypeHandle); } - protected override unsafe int GetValueHashCode(NamedTypeLookupResult value) + protected unsafe override int GetValueHashCode(NamedTypeLookupResult value) { return value.RuntimeTypeHandleHashcode; } @@ -122,7 +122,7 @@ private static int _rotl(int value, int shift) return (int)(((uint)value << shift) | ((uint)value >> (32 - shift))); } - protected override unsafe int GetKeyHashCode(QTypeDefinition key) + protected unsafe override int GetKeyHashCode(QTypeDefinition key) { return key.Token.GetHashCode() ^ _rotl(key.Reader.GetHashCode(), 8); } @@ -132,7 +132,7 @@ protected override bool CompareKeyToValue(QTypeDefinition key, NamedTypeLookupRe key.Reader.Equals(value.QualifiedTypeDefinition.Reader); } - protected override unsafe int GetValueHashCode(NamedTypeLookupResult value) + protected unsafe override int GetValueHashCode(NamedTypeLookupResult value) { return value.QualifiedTypeDefinition.Token.GetHashCode() ^ _rotl(value.QualifiedTypeDefinition.Reader.GetHashCode(), 8); } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs index 4d13dbf569eb1..06a7ade1eaa85 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.SignatureParsing.cs @@ -479,7 +479,7 @@ private bool TypeSignatureHasVarsNeedingCallingConventionConverter(ref NativePar for (uint i = 0; i < data; i++) result = TypeSignatureHasVarsNeedingCallingConventionConverter(ref parser, moduleHandle, context, HasVarsInvestigationLevel.NotParameter) || result; - if (result && (investigationLevel == HasVarsInvestigationLevel.Parameter)) + if ((result == true) && (investigationLevel == HasVarsInvestigationLevel.Parameter)) { if (!TryComputeHasInstantiationDeterminedSize(genericTypeDef, context, out result)) Environment.FailFast("Unable to setup calling convention converter correctly"); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs index 310534e09451c..702baa4e22ecc 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs @@ -25,11 +25,6 @@ namespace Internal.Runtime.TypeLoader { internal class Callbacks : TypeLoaderCallbacks { - public override TypeManagerHandle GetModuleForMetadataReader(MetadataReader reader) - { - return TypeLoaderEnvironment.Instance.ModuleList.GetModuleForMetadataReader(reader); - } - public override bool TryGetConstructedGenericTypeForComponents(RuntimeTypeHandle genericTypeDefinitionHandle, RuntimeTypeHandle[] genericTypeArgumentHandles, out RuntimeTypeHandle runtimeTypeHandle) { return TypeLoaderEnvironment.Instance.TryGetConstructedGenericTypeForComponents(genericTypeDefinitionHandle, genericTypeArgumentHandles, out runtimeTypeHandle); @@ -50,11 +45,6 @@ public override bool GetRuntimeMethodHandleComponents(RuntimeMethodHandle runtim return TypeLoaderEnvironment.Instance.TryGetRuntimeMethodHandleComponents(runtimeMethodHandle, out declaringTypeHandle, out nameAndSignature, out genericMethodArgs); } - public override RuntimeMethodHandle GetRuntimeMethodHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string methodName, RuntimeSignature methodSignature, RuntimeTypeHandle[] genericMethodArgs) - { - return TypeLoaderEnvironment.Instance.GetRuntimeMethodHandleForComponents(declaringTypeHandle, methodName, methodSignature, genericMethodArgs); - } - public override bool CompareMethodSignatures(RuntimeSignature signature1, RuntimeSignature signature2) { return TypeLoaderEnvironment.Instance.CompareMethodSignatures(signature1, signature2); @@ -82,11 +72,6 @@ public override bool GetRuntimeFieldHandleComponents(RuntimeFieldHandle runtimeF return TypeLoaderEnvironment.Instance.TryGetRuntimeFieldHandleComponents(runtimeFieldHandle, out declaringTypeHandle, out fieldName); } - public override RuntimeFieldHandle GetRuntimeFieldHandleForComponents(RuntimeTypeHandle declaringTypeHandle, string fieldName) - { - return TypeLoaderEnvironment.Instance.GetRuntimeFieldHandleForComponents(declaringTypeHandle, fieldName); - } - public override IntPtr ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(IntPtr unboxingFunctionPointer, RuntimeTypeHandle declaringType) { return TypeLoaderEnvironment.ConvertUnboxingFunctionPointerToUnderlyingNonUnboxingPointer(unboxingFunctionPointer, declaringType); diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs index 09332e167c4b0..66cd911473ffa 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeDesc.Runtime.cs @@ -84,8 +84,10 @@ internal bool RetrieveRuntimeTypeHandleIfPossible() if (state != null && state.AttemptedAndFailedToRetrieveTypeHandle) return false; - if (type is DefType typeAsDefType) + if (type is DefType) { + DefType typeAsDefType = (DefType)type; + TypeDesc typeDefinition = typeAsDefType.GetTypeDefinition(); RuntimeTypeHandle typeDefHandle = typeDefinition.RuntimeTypeHandle; if (typeDefHandle.IsNull()) @@ -153,8 +155,10 @@ internal bool RetrieveRuntimeTypeHandleIfPossible() } } } - else if (type is ParameterizedType typeAsParameterType) + else if (type is ParameterizedType) { + ParameterizedType typeAsParameterType = (ParameterizedType)type; + if (typeAsParameterType.ParameterType.RetrieveRuntimeTypeHandleIfPossible()) { RuntimeTypeHandle rtth; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs index 1f2b9cd01f000..55923303d641e 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/TypeSystemContext.Runtime.cs @@ -321,8 +321,10 @@ protected override int GetValueHashCode(MethodDesc value) protected override bool CompareKeyToValue(RuntimeMethodKey key, MethodDesc value) { - if (value is RuntimeMethodDesc runtimeMethod) + if (value is RuntimeMethodDesc) { + RuntimeMethodDesc runtimeMethod = (RuntimeMethodDesc)value; + if (key._unboxingStub != runtimeMethod.UnboxingStub) return false; diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj index b9532d1de4c51..73332581e5025 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj @@ -270,6 +270,7 @@ + @@ -280,6 +281,7 @@ + @@ -326,6 +328,8 @@ + + System\Runtime\CompilerServices\__BlockAllReflectionAttribute.cs diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QHandles.NativeFormat.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System/Reflection/Runtime/General/QHandles.NativeFormat.cs similarity index 99% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QHandles.NativeFormat.cs rename to src/coreclr/nativeaot/System.Private.TypeLoader/src/System/Reflection/Runtime/General/QHandles.NativeFormat.cs index 087f2cfdcf087..08ad466e41a0c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QHandles.NativeFormat.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System/Reflection/Runtime/General/QHandles.NativeFormat.cs @@ -14,6 +14,7 @@ namespace System.Reflection.Runtime.General { + public partial struct QMethodDefinition { public QMethodDefinition(MetadataReader reader, MethodHandle handle) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QHandles.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System/Reflection/Runtime/General/QHandles.cs similarity index 93% rename from src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QHandles.cs rename to src/coreclr/nativeaot/System.Private.TypeLoader/src/System/Reflection/Runtime/General/QHandles.cs index f8c7e014c857e..2f47be124a0a2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/QHandles.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/System/Reflection/Runtime/General/QHandles.cs @@ -8,15 +8,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.CompilerServices; using Internal.Metadata.NativeFormat; using Internal.Runtime.TypeLoader; namespace Internal.Reflection.Core { - [ReflectionBlocked] - [CLSCompliant(false)] public struct QScopeDefinition : IEquatable { public QScopeDefinition(MetadataReader reader, ScopeDefinitionHandle handle) @@ -63,8 +60,6 @@ public override int GetHashCode() namespace System.Reflection.Runtime.General { - [ReflectionBlocked] - [CLSCompliant(false)] public struct QHandle : IEquatable { public QHandle(MetadataReader reader, Handle handle) @@ -101,8 +96,6 @@ public override int GetHashCode() private readonly Handle _handle; } - [ReflectionBlocked] - [CLSCompliant(false)] public partial struct QMethodDefinition { private QMethodDefinition(object reader, int token) @@ -127,8 +120,6 @@ public static QMethodDefinition FromObjectAndInt(object reader, int token) private readonly int _handle; } - [ReflectionBlocked] - [CLSCompliant(false)] public partial struct QTypeDefinition { public object Reader { get { return _reader; } } @@ -143,8 +134,6 @@ public partial struct QTypeDefinition } - [ReflectionBlocked] - [CLSCompliant(false)] public partial struct QTypeDefRefOrSpec { public object Reader { get { return _reader; } } @@ -158,8 +147,6 @@ public partial struct QTypeDefRefOrSpec private readonly int _handle; } - [ReflectionBlocked] - [CLSCompliant(false)] public struct QGenericParameter : IEquatable { public QGenericParameter(MetadataReader reader, GenericParameterHandle handle) diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs index b1ffb46e39c9b..b6901b1ce50c3 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -73,20 +73,20 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe // [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewObject")] - private static extern unsafe object RhNewObject(MethodTable* pEEType); + private static unsafe extern object RhNewObject(MethodTable* pEEType); internal static unsafe object RhNewObject(EETypePtr pEEType) => RhNewObject(pEEType.ToPointer()); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewArray")] - private static extern unsafe Array RhNewArray(MethodTable* pEEType, int length); + private static unsafe extern Array RhNewArray(MethodTable* pEEType, int length); internal static unsafe Array RhNewArray(EETypePtr pEEType, int length) => RhNewArray(pEEType.ToPointer(), length); [DllImport(RuntimeLibrary)] - internal static extern unsafe void RhAllocateNewObject(IntPtr pEEType, uint flags, void* pResult); + internal static unsafe extern void RhAllocateNewObject(IntPtr pEEType, uint flags, void* pResult); [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhpFallbackFailFast")] diff --git a/src/coreclr/nativeaot/docs/optimizing.md b/src/coreclr/nativeaot/docs/optimizing.md index cc31c98df1539..aeee66fa2f41d 100644 --- a/src/coreclr/nativeaot/docs/optimizing.md +++ b/src/coreclr/nativeaot/docs/optimizing.md @@ -12,6 +12,12 @@ To specify a switch, add a new property to your project file with one or more of under the `` node of your project file. +## Options related to library features + +Native AOT supports enabling and disabling all [documented framework library features](https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming-options#trimming-framework-library-features). For example, to remove globalization specific code and data, add a `true` property to your project. Disabling a framework feature (or enabling a minimal mode of the feature) can result in significant size savings. + +🛈 Native AOT difference: The `EnableUnsafeBinaryFormatterSerialization` framework switch is already set to the optimal value of `false` (removing the support for [obsolete](https://github.com/dotnet/designs/blob/21b274dbc21e4ae54b7e4c5dbd5ef31e439e78db/accepted/2020/better-obsoletion/binaryformatter-obsoletion.md) binary serialization). + ## Options related to trimming The Native AOT compiler supports the [documented options](https://docs.microsoft.com/en-us/dotnet/core/deploying/trim-self-contained) for removing unused code (trimming). By default, the compiler tries to very conservatively remove some of the unused code. @@ -20,21 +26,16 @@ The Native AOT compiler supports the [documented options](https://docs.microsoft By default, the compiler tries to maximize compatibility with existing .NET code at the expense of compilation speed and size of the output executable. This allows people to use their existing code that worked well in a fully dynamic mode without hitting issues caused by trimming. To read more about reflection, see the [Reflection in AOT mode](reflection-in-aot-mode.md) document. -To enable more aggressive removal of unreferenced code, set the `` property to `link`. - -To aid in troubleshooting some of the most common problems related to trimming add `true` to your project. This ensures types are preserved in their entirety, but the extra members that would otherwise be trimmed cannot be used in runtime reflection. This mode can turn some spurious `NullReferenceExceptions` (caused by reflection APIs returning a null) caused by trimming into more actionable exceptions. - -The Native AOT compiler can remove unused metadata more effectively than non-Native deployment models. For example, it's possible to remove names and metadata for methods while keeping the native code of the method. The higher efficiency of trimming in Native AOT can result in differences in what's visible to reflection at runtime in trimming-unfriendly code. To increase compatibility with the less efficient non-Native trimming, set the `` property to `false`. This compatibility mode is not necessary if there are no trimming warnings. - -## Options related to library features +🛈 Native AOT difference: the `TrimMode` of framework assemblies is set to `link` by default. To compile entire framework assemblies, use `TrimmerRootAssembly` to root the selected assemblies. It's not recommended to root the entire framework. -Native AOT supports enabling and disabling all [documented framework library features](https://docs.microsoft.com/en-us/dotnet/core/deploying/trimming-options#trimming-framework-library-features). For example, to remove globalization specific code and data, add a `true` property to your project. Disabling a framework feature (or enabling a minimal mode of the feature) can result in significant size savings. +To enable more aggressive removal of unreferenced code, set the `` property to `link`. -Since `PublishTrimmed` is implied to be true with Native AOT, some framework features such as binary serialization are disabled by default. +To aid in troubleshooting some of the most common problems related to trimming add `true` to your project. This ensures types are preserved in their entirety, but the extra members that would otherwise be trimmed cannot be used in runtime reflection. This mode can turn some spurious `NullReferenceExceptions` (caused by reflection APIs returning a null) caused by trimming into more actionable exceptions. ## Options related to metadata generation * `false`: this disables generation of stack trace metadata that provides textual names in stack traces. This is for example the text string one gets by calling `Exception.ToString()` on a caught exception. With this option disabled, stack traces will still be generated, but will be based on reflection metadata alone (they might be less complete). +* `true`: allows the compiler to remove reflection metadata from things that were not visible targets of reflection. By default, the compiler keeps metadata for everything that was compiled. With this option turned on, reflection metadata (and therefore reflection) will only be available for visible targets of reflection. Visible targets of reflection are things like assemblies rooted from the project file, RD.XML, ILLinkTrim descriptors, DynamicallyAccessedMembers annotations or DynamicDependency annotations. ## Options related to code generation * `Speed`: when generating optimized code, favor code execution speed. diff --git a/src/coreclr/nativeaot/docs/reflection-free-mode.md b/src/coreclr/nativeaot/docs/reflection-free-mode.md index f4acb394c67c9..644421e36c1f1 100644 --- a/src/coreclr/nativeaot/docs/reflection-free-mode.md +++ b/src/coreclr/nativeaot/docs/reflection-free-mode.md @@ -34,7 +34,7 @@ Think of: Reflection-free mode **supports a limited set of reflection APIs** that keep their expected semantics. * `typeof(SomeType)` will return a `System.Type` that can be compared with results of other `typeof` expressions or results of `Object.GetType()` calls. The patterns commonly used in perf optimizations of generic code (e.g. `typeof(T) == typeof(byte)`) will work fine, and so will `obj.GetType() == typeof(SomeType)`. -* Following APIs on `System.Type` work: `TypeHandle`, `UnderlyingSystemType`, `BaseType`, `IsByRefLike`, `IsValueType`, `GetTypeCode`, `GetHashCode`, `GetElementType`, `GetInterfaces`, `HasElementType`, `IsArray`, `IsByRef`, `IsPointer`, `IsPrimitive`, `IsAssignableFrom`, `IsAssignableTo`, `IsInstanceOfType`. +* Following APIs on `System.Type` work: `TypeHandle`, `UnderlyingSystemType`, `BaseType`, `IsByRefLike`, `IsValueType`, `GetTypeCode`, `GetHashCode`, `GetElementType`, `GetInterfaces`, `HasElementType`, `IsArray`, `IsByRef`, `IsPointer`, `IsPrimitive`. * `Activator.CreateInstance()` will work. The compiler statically analyzes and expands this to efficient code at compile time. No reflection is involved at runtime. * `Assembly.GetExecutingAssembly()` will return a `System.Reflection.Assembly` that can be compared with other runtime `Assembly` instances. This is mostly to make it possible to use the `NativeLibrary.SetDllImportResolver` API. diff --git a/src/coreclr/nativeaot/nativeaot.sln b/src/coreclr/nativeaot/nativeaot.sln index 7812cd25d4925..f2bbfe6e9fb4a 100644 --- a/src/coreclr/nativeaot/nativeaot.sln +++ b/src/coreclr/nativeaot/nativeaot.sln @@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "S EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.DisabledReflection", "System.Private.DisabledReflection\src\System.Private.DisabledReflection.csproj", "{ADA691AE-4E1F-4212-97E6-51A27EFCE7E4}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.Reflection.Core", "System.Private.Reflection.Core\src\System.Private.Reflection.Core.csproj", "{6147AF1A-5054-492A-9309-FA868A184414}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.Reflection.Execution", "System.Private.Reflection.Execution\src\System.Private.Reflection.Execution.csproj", "{7498DD7C-76C1-4912-AF72-DA84E05B568F}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.StackTraceMetadata", "System.Private.StackTraceMetadata\src\System.Private.StackTraceMetadata.csproj", "{33CAE331-16EE-443C-A0CC-4337B94A02AD}" diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index dd7e99c665b10..db7d114b5e879 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -96,8 +96,6 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define _M_LOONGARCH64 1 #elif defined(__s390x__) && !defined(_M_S390X) #define _M_S390X 1 -#elif defined(__powerpc__) && !defined(_M_PPC64) -#define _M_PPC64 1 #endif #if defined(_M_IX86) && !defined(HOST_X86) @@ -112,8 +110,6 @@ typedef PVOID NATIVE_LIBRARY_HANDLE; #define HOST_LOONGARCH64 #elif defined(_M_S390X) && !defined(HOST_S390X) #define HOST_S390X -#elif defined(_M_PPC64) && !defined(HOST_POWERPC64) -#define HOST_POWERPC64 #endif #endif // !_MSC_VER @@ -2403,153 +2399,6 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { } KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; -#elif defined(HOST_POWERPC64) - -// There is no context for ppc64le defined in winnt.h, -// so we re-use the amd64 values. -#define CONTEXT_PPC64 0x100000 - -#define CONTEXT_CONTROL (CONTEXT_PPC64 | 0x1L) -#define CONTEXT_INTEGER (CONTEXT_PPC64 | 0x2L) -#define CONTEXT_FLOATING_POINT (CONTEXT_PPC64 | 0x4L) - -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - -#define CONTEXT_ALL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - -#define CONTEXT_EXCEPTION_ACTIVE 0x8000000 -#define CONTEXT_SERVICE_ACTIVE 0x10000000 -#define CONTEXT_EXCEPTION_REQUEST 0x40000000 -#define CONTEXT_EXCEPTION_REPORTING 0x80000000 - -typedef struct DECLSPEC_ALIGN(16) _CONTEXT { - - // - // Control flags. - // - - DWORD ContextFlags; - - // - // Integer Registers - // - - DWORD64 R0; - DWORD64 R1; - DWORD64 R2; - DWORD64 R3; - DWORD64 R4; - DWORD64 R5; - DWORD64 R6; - DWORD64 R7; - DWORD64 R8; - DWORD64 R9; - DWORD64 R10; - DWORD64 R11; - DWORD64 R12; - DWORD64 R13; - DWORD64 R14; - DWORD64 R15; - DWORD64 R16; - DWORD64 R17; - DWORD64 R18; - DWORD64 R19; - DWORD64 R20; - DWORD64 R21; - DWORD64 R22; - DWORD64 R23; - DWORD64 R24; - DWORD64 R25; - DWORD64 R26; - DWORD64 R27; - DWORD64 R28; - DWORD64 R29; - DWORD64 R30; - DWORD64 R31; - - // - // Floaring Point Registers - // - - DWORD64 F0; - DWORD64 F1; - DWORD64 F2; - DWORD64 F3; - DWORD64 F4; - DWORD64 F5; - DWORD64 F6; - DWORD64 F7; - DWORD64 F8; - DWORD64 F9; - DWORD64 F10; - DWORD64 F11; - DWORD64 F12; - DWORD64 F13; - DWORD64 F14; - DWORD64 F15; - DWORD64 F16; - DWORD64 F17; - DWORD64 F18; - DWORD64 F19; - DWORD64 F20; - DWORD64 F21; - DWORD64 F22; - DWORD64 F23; - DWORD64 F24; - DWORD64 F25; - DWORD64 F26; - DWORD64 F27; - DWORD64 F28; - DWORD64 F29; - DWORD64 F30; - DWORD64 F31; - DWORD64 Fpscr; - - // - // Control Registers - // - - DWORD64 Nip; - DWORD64 Msr; - DWORD64 Ctr; - DWORD64 Link; - - DWORD Xer; - DWORD Ccr; - - -} CONTEXT, *PCONTEXT, *LPCONTEXT; - -// -// Nonvolatile context pointer record. -// - -typedef struct _KNONVOLATILE_CONTEXT_POINTERS { - PDWORD64 R14; - PDWORD64 R15; - PDWORD64 R16; - PDWORD64 R17; - PDWORD64 R18; - PDWORD64 R19; - PDWORD64 R20; - PDWORD64 R21; - PDWORD64 R22; - PDWORD64 R23; - PDWORD64 R24; - PDWORD64 R25; - PDWORD64 R26; - PDWORD64 R27; - PDWORD64 R28; - PDWORD64 R29; - PDWORD64 R30; - PDWORD64 R31; - - // - // Need to add Floating point non-volatile registers. - // - -} KNONVOLATILE_CONTEXT_POINTERS, *PKNONVOLATILE_CONTEXT_POINTERS; - #else #error Unknown architecture for defining CONTEXT. #endif @@ -2687,8 +2536,6 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_ #define PAL_CS_NATIVE_DATA_SIZE 96 #elif defined(__linux__) && defined(HOST_S390X) #define PAL_CS_NATIVE_DATA_SIZE 96 -#elif defined(__linux__) && defined(HOST_POWERPC64) -#define PAL_CS_NATIVE_DATA_SIZE 96 #elif defined(__NetBSD__) && defined(__amd64__) #define PAL_CS_NATIVE_DATA_SIZE 96 #elif defined(__NetBSD__) && defined(__earm__) diff --git a/src/coreclr/pal/inc/pal_endian.h b/src/coreclr/pal/inc/pal_endian.h index 43a8167562eee..6822b004ddaaf 100644 --- a/src/coreclr/pal/inc/pal_endian.h +++ b/src/coreclr/pal/inc/pal_endian.h @@ -16,7 +16,7 @@ extern "C++" { inline UINT16 SWAP16(UINT16 x) { - return (UINT16)((x >> 8) | (x << 8)); + return (x >> 8) | (x << 8); } inline UINT32 SWAP32(UINT32 x) diff --git a/src/coreclr/pal/inc/rt/intsafe.h b/src/coreclr/pal/inc/rt/intsafe.h new file mode 100644 index 0000000000000..d793d357a3ba3 --- /dev/null +++ b/src/coreclr/pal/inc/rt/intsafe.h @@ -0,0 +1,1401 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/****************************************************************** +* * +* intsafe.h -- This module defines helper functions to prevent * +* integer overflow issues. * +* * +* * +******************************************************************/ +#ifndef _INTSAFE_H_INCLUDED_ +#define _INTSAFE_H_INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include // for IN, etc. + +#define INTSAFE_E_ARITHMETIC_OVERFLOW ((HRESULT)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW + +#ifndef LOWORD +#define LOWORD(l) ((WORD)(((DWORD_PTR)(l)) & 0xffff)) +#endif + +#ifndef HIWORD +#define HIWORD(l) ((WORD)(((DWORD_PTR)(l)) >> 16)) +#endif + +#define HIDWORD(_qw) ((ULONG)((_qw) >> 32)) +#define LODWORD(_qw) ((ULONG)(_qw)) + +#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \ + || defined(_M_AMD64) || defined(__ARM_ARCH) || defined(_M_S390X) || defined(_M_LOONGARCH64) + +#ifndef UInt32x32To64 +#define UInt32x32To64(a, b) ((unsigned __int64)((ULONG)(a)) * (unsigned __int64)((ULONG)(b))) +#endif + +#elif defined(_M_IX86) + +#ifndef UInt32x32To64 +#define UInt32x32To64(a, b) (unsigned __int64)((unsigned __int64)(ULONG)(a) * (ULONG)(b)) +#endif + +#else + +#error Must define a target architecture. + +#endif + +// +// It is common for -1 to be used as an error value for various types +// +#define USHORT_ERROR (0xffff) +#define INT_ERROR (-1) +#define LONG_ERROR (-1L) +#define UINT_ERROR (0xffffffff) +#define ULONG_ERROR (0xffffffffUL) +#ifdef _MSC_VER +#define ULONGLONG_ERROR (0xffffffffffffffffui64) +#define HIDWORD_MASK (0xffffffff00000000ui64) +#else // _MSC_VER +#define ULONGLONG_ERROR (0xffffffffffffffffULL) +#define HIDWORD_MASK (0xffffffff00000000ULL) +#endif // _MSC_VER +#ifdef HOST_64BIT +#define SIZET_ERROR ULONGLONG_ERROR +#else +#define SIZET_ERROR ULONG_ERROR +#endif + +// +// We make some assumptions about the sizes of various types. Let's be +// explicit about those assumptions and check them. +// +C_ASSERT(sizeof(unsigned short) == 2); +C_ASSERT(sizeof(unsigned int) == 4); +C_ASSERT(sizeof(ULONG) == 4); + +// +// INT -> signed char conversion +// +__inline +HRESULT +IntToSignedChar( + IN INT iOperand, + OUT signed char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if ((iOperand >= -128) && (iOperand <= 127)) + { + *pch = (signed char)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> UCHAR conversion +// +__inline +HRESULT +IntToUChar( + IN INT iOperand, + OUT UCHAR* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if ((iOperand >= 0) && (iOperand <= 255)) + { + *pch = (UCHAR)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// LONG -> UCHAR conversion +// +__inline +HRESULT +LongToUChar( + IN LONG lOperand, + OUT UCHAR* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if ((lOperand >= 0) && (lOperand <= 255)) + { + *pch = (UCHAR)lOperand; + hr = S_OK; + } + + return hr; +} + +// +// __inline is not sufficient. __forceinline is necessary. +// If the function is not inlined and you link .objs compiled with different compiler switches, +// you get one or the other function arbitrarily chosen. +// +// INT -> CHAR conversion +// +__forceinline +HRESULT +IntToChar( + IN INT iOperand, + OUT CHAR* pch) +{ +#ifdef _CHAR_UNSIGNED + return IntToUChar(iOperand, (UCHAR*)pch); +#else + return IntToSignedChar(iOperand, (signed char*)pch); +#endif +} + +// +// INT -> USHORT conversion +// +__inline +HRESULT +IntToUShort( + IN INT iOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if ((iOperand >= 0) && (iOperand <= USHRT_MAX)) + { + *pusResult = (USHORT)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> UINT conversion +// +__inline +HRESULT +IntToUInt( + IN INT iOperand, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if (iOperand >= 0) + { + *puResult = (UINT)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> ULONG conversion +// +__inline +HRESULT +IntToULong( + IN INT iOperand, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if (iOperand >= 0) + { + *pulResult = (ULONG)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// INT -> ULONGLONG conversion +// +__inline +HRESULT +IntToULongLong( + IN INT iOperand, + OUT ULONGLONG* pullResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pullResult = ULONG_ERROR; + + if (iOperand >= 0) + { + *pullResult = (ULONGLONG)iOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> signed char conversion +// +__inline +HRESULT +UIntToSignedChar( + IN UINT uOperand, + OUT signed char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (uOperand <= 127) + { + *pch = (signed char)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> UCHAR conversion +// +__inline +HRESULT +UIntToUChar( + IN UINT uOperand, + OUT UCHAR* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (uOperand <= 255) + { + *pch = (UCHAR)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> BYTE conversion +// +#define UIntToByte UIntToUChar + +// +// __inline is not sufficient. __forceinline is necessary. +// If the function is not inlined and you link .objs compiled with different compiler switches, +// you get one or the other function arbitrarily chosen. +// +// UINT -> CHAR conversion +// +__forceinline +HRESULT +UIntToChar( + IN UINT uOperand, + OUT CHAR* pch) +{ +#ifdef _CHAR_UNSIGNED + return UIntToUChar(uOperand, (UCHAR*)pch); +#else + return UIntToSignedChar(uOperand, (signed char*)pch); +#endif // _CHAR_UNSIGNED +} + +// +// UINT -> INT conversion +// +__inline +HRESULT +UIntToInt( + IN UINT uOperand, + OUT INT* piResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *piResult = INT_ERROR; + + if (uOperand <= INT_MAX) + { + *piResult = (INT)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT -> LONG conversion +// +__inline +HRESULT +UIntToLong( + IN UINT Operand, + OUT LONG* Result) +{ + if (Operand <= _I32_MAX) + { + *Result = (LONG)Operand; + return S_OK; + } + else + { + *Result = LONG_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// UINT -> ULONG conversion +// +__inline +HRESULT +UIntToULong( + IN UINT uOperand, + OUT ULONG* pulResult) +{ + *pulResult = (ULONG)uOperand; + + return S_OK; +} + +// +// ULONG -> UCHAR conversion +// +__inline +HRESULT +ULongToSignedChar( + IN ULONG ulOperand, + OUT signed char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (ulOperand <= 127) + { + *pch = (signed char)ulOperand; + hr = S_OK; + } + + return hr; +} + +// +// ULONG -> UCHAR conversion +// +__inline +HRESULT +ULongToUChar( + IN ULONG ulOperand, + OUT unsigned char* pch) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pch = 0; + + if (ulOperand <= 255) + { + *pch = (unsigned char)ulOperand; + hr = S_OK; + } + + return hr; +} + +// +// __inline is not sufficient. __forceinline is necessary. +// If the function is not inlined and you link .objs compiled with different compiler switches, +// you get one or the other function arbitrarily chosen. +// +// ULONG -> CHAR conversion +// +__forceinline +HRESULT +ULongToChar( + IN ULONG ulOperand, + OUT CHAR* pch) +{ +#ifdef _CHAR_UNSIGNED + return ULongToUChar(ulOperand, (unsigned char*)pch); +#else + return ULongToSignedChar(ulOperand, (signed char*)pch); +#endif // _CHAR_UNSIGNED +} + +// +// ULONG -> USHORT conversion +// +__inline +HRESULT +ULongToUShort( + IN ULONG ulOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (ulOperand <= USHRT_MAX) + { + *pusResult = (USHORT)ulOperand; + hr = S_OK; + } + + return hr; +} + +// +// ULONG -> INT conversion +// +__inline +HRESULT +ULongToInt( + IN ULONG ulOperand, + OUT INT* piResult) +{ + if (ulOperand <= INT_MAX) + { + *piResult = (INT)ulOperand; + return S_OK; + } + else + { + *piResult = INT_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// ULONG -> UINT conversion +// +__inline +HRESULT +ULongToUInt( + IN ULONG ulOperand, + OUT UINT* puResult) +{ + *puResult = (UINT)ulOperand; + + return S_OK; +} + +// +// ULONG -> LONG conversion +// +__inline +HRESULT +ULongToLong( + IN ULONG Operand, + OUT LONG* Result) +{ + if (Operand <= _I32_MAX) + { + *Result = (LONG)Operand; + return S_OK; + } + else + { + *Result = LONG_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// ULONGLONG -> INT conversion +// +__inline +HRESULT +ULongLongToInt( + IN ULONGLONG ullOperand, + OUT INT* piResult) +{ + if (ullOperand <= INT_MAX) + { + *piResult = (INT)ullOperand; + return S_OK; + } + else + { + *piResult = INT_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// ULONGLONG -> LONG conversion +// +__inline +HRESULT +ULongLongToLong( + IN ULONGLONG Operand, + OUT LONG* Result) +{ + if (Operand <= _I32_MAX) + { + *Result = (LONG)Operand; + return S_OK; + } + else + { + *Result = LONG_ERROR; + return INTSAFE_E_ARITHMETIC_OVERFLOW; + } +} + +// +// UINT -> USHORT conversion +// +__inline +HRESULT +UIntToUShort( + IN UINT uOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (uOperand <= USHRT_MAX) + { + *pusResult = (USHORT)uOperand; + hr = S_OK; + } + + return hr; +} + +// +// ULONGLONG -> USHORT conversion +// +__inline +HRESULT +ULongLongToUShort( + IN ULONGLONG ullOperand, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + USHORT usResult = USHORT_ERROR; + + if (ullOperand <= USHRT_MAX) + { + usResult = (USHORT)ullOperand; + hr = S_OK; + } + *pusResult = usResult; + + return hr; +} + +// +// ULONGLONG -> ULONG conversion +// +__inline +HRESULT +ULongLongToULong( + IN ULONGLONG ullOperand, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if (ullOperand <= _UI32_MAX) + { + *pulResult = (ULONG)ullOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR -> ULONG conversion +// ULONG_PTR -> ULONG conversion +// +#ifdef HOST_64BIT + +#define UIntPtrToULong ULongLongToULong +#define ULongPtrToULong ULongLongToULong + +#else + +__inline +HRESULT +UIntPtrToULong( + IN UINT_PTR Operand, + OUT ULONG* pResult) +{ + *pResult = (ULONG)Operand; + return S_OK; +} + +__inline +HRESULT +ULongPtrToULong( + IN ULONG_PTR Operand, + OUT ULONG* pResult) +{ + *pResult = (ULONG)Operand; + return S_OK; +} + +#endif + +// +// ULONGLONG -> UINT conversion +// +__inline +HRESULT +ULongLongToUInt( + IN ULONGLONG ullOperand, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if (ullOperand <= UINT_MAX) + { + *puResult = (UINT)ullOperand; + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR -> UINT conversion +// ULONG_PTR -> UINT conversion +// +#ifdef HOST_64BIT + +#define UIntPtrToUInt ULongLongToUInt +#define ULongPtrToUInt ULongLongToUInt + +#else + +__inline +HRESULT +UIntPtrToUInt( + IN UINT_PTR Operand, + OUT UINT* pResult) +{ + *pResult = (UINT)Operand; + return S_OK; +} + +__inline +HRESULT +ULongPtrToUInt( + IN ULONG_PTR Operand, + OUT UINT* pResult) +{ + *pResult = (UINT)Operand; + return S_OK; +} + +#endif + +// +// * -> BYTE conversion (BYTE is always unsigned char) +// +#define IntToByte IntToUChar +#define UIntToByte UIntToUChar +#define LongToByte LongToUChar +#define ULongToByte ULongToUChar + +// +// * -> WORD conversion (WORD is always unsigned short) +// +#define IntToWord IntToUShort +#define LongToWord LongToUShort +#define LongLongToWord LongLongToUShort +#define UIntToWord UIntToUShort +#define ULongToWord ULongToUShort +#define ULongLongToWord ULongLongToUShort +#define UIntPtrToWord UIntPtrToUShort +#define ULongPtrToWord ULongPtrToUShort +#define SizeTToWord SizeTToUShort +#define SIZETToWord SIZETToUShort + +// +// WORD -> * conversion (WORD is always unsigned short) +// +#define WordToUChar UShortToUChar +#define WordToByte UShortToByte +#define WordToChar UShortToChar +#define WordToSignedChar UShortToSignedChar +#define WordToInt UShortToInt +#define WordToLong UShortToLong +#define WordToLongLong UShortToLongLong +#define WordToIntPtr UShortToIntPtr +#define WordToLongPtr UShortToLongPtr + +// +// * -> DWORD conversion (DWORD is always ULONG) +// +#define CharToDWord CharToULong +#define SignedCharToDWord SignedCharToULong +#define ShortToDWord ShortToULong +#define IntToDWord IntToULong +#define LongToDWord LongToULong +#define LongLongToDWord LongLongToULong +#define UIntToDWord UIntToULong +#define ULongLongToDWord ULongLongToULong +#define IntPtrToDWord IntPtrToULong +#define LongPtrToDWord LongPtrToULong +#define UIntPtrToDWord UIntPtrToULong +#define ULongPtrToDWord ULongPtrToULong +#define SizeTToDWord SizeTToULong +#define SIZETToDWord SIZETToULong + +// +// DWORD -> * conversion (DWORD is always ULONG) +// +#define DWordToChar ULongToChar +#define DWordToUChar ULongToUChar +#define DWordToByte ULongToByte +#define DWordToSignedChar ULongToSignedChar +#define DWordToUShort ULongToUShort +#define DWordToUInt ULongToUInt +#define DWordToInt ULongToInt +#define DWordToLong ULongToLong +#define DWordToLongLong ULongToLongLong +#define DWordToIntPtr ULongToIntPtr +#define DWordToLongPtr ULongToLongPtr + + +// +// * -> UINT_PTR conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64) +// +#ifdef HOST_64BIT +#define CharToUIntPtr CharToULongLong +#define SignedCharToUIntPtr SignedCharToULongLong +#define ShortToUIntPtr ShortToULongLong +#define IntToUIntPtr IntToULongLong +#define LongToUIntPtr LongToULongLong +#define LongLongToUIntPtr LongLongToULongLong +#define IntPtrToUIntPtr IntPtrToULongLong +#define LongPtrToUIntPtr LongPtrToULongLong +#else +#define CharToUIntPtr CharToUInt +#define SignedCharToUIntPtr SignedCharToUInt +#define ShortToUIntPtr ShortToUInt + +__inline +HRESULT +IntToUIntPtr( + IN INT iOperand, + OUT UINT_PTR* puResult) +{ + return IntToUInt(iOperand, (UINT*)puResult); +} + +#define LongToUIntPtr LongToUInt +#define LongLongToUIntPtr LongLongToUInt + +#define IntPtrToUIntPtr IntPtrToUInt +#define LongPtrToUIntPtr LongPtrToUInt +#endif + +__inline +HRESULT +ULongLongToUIntPtr( + IN ULONGLONG ullOperand, + OUT UINT_PTR* puResult) +{ +#ifdef HOST_64BIT + *puResult = ullOperand; + return S_OK; +#else + return ULongLongToUInt(ullOperand, (UINT*)puResult); +#endif +} + + +// +// UINT_PTR -> * conversion (UINT_PTR is UINT on Win32, ULONGLONG on Win64) +// +#ifdef HOST_64BIT +#define UIntPtrToUShort ULongLongToUShort +#define UIntPtrToInt ULongLongToInt +#define UIntPtrToLong ULongLongToLong +#define UIntPtrToLongLong ULongLongToLongLong +#define UIntPtrToIntPtr ULongLongToIntPtr +#define UIntPtrToLongPtr ULongLongToLongPtr +#else + +__inline +HRESULT +UIntPtrToUShort( + IN UINT_PTR uOperand, + OUT USHORT* pusResult) +{ + return UIntToUShort((UINT)uOperand, pusResult); +} + +__inline +HRESULT +UIntPtrToInt( + IN UINT_PTR uOperand, + OUT INT* piResult) +{ + return UIntToInt((UINT)uOperand, piResult); +} + +__inline +HRESULT +UIntPtrToLong( + IN UINT_PTR Operand, + OUT LONG* Result) +{ + return UIntToLong((UINT)Operand, Result); +} + +#define UIntPtrToLongLong UIntToLongLong +#define UIntPtrToIntPtr UIntToIntPtr +#define UIntPtrToLongPtr UIntToLongPtr +#endif + + +// +// * -> ULONG_PTR conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64) +// +#ifdef HOST_64BIT +#define CharToULongPtr CharToULongLong +#define SignedCharToULongPtr SignedCharToULongLong +#define ShortToULongPtr ShortToULongLong +#define IntToULongPtr IntToULongLong +#define LongToULongPtr LongToULongLong +#define LongLongToULongPtr LongLongToULongLong +#define IntPtrToULongPtr IntPtrToULongLong +#define LongPtrToULongPtr LongPtrToULongLong +#else +#define CharToULongPtr CharToULong +#define SignedCharToULongPtr SignedCharToULong +#define ShortToULongPtr ShortToULong + +__inline +HRESULT +IntToULongPtr( + IN INT iOperand, + OUT ULONG_PTR* pulResult) +{ + return IntToULong(iOperand, (ULONG*)pulResult); +} + +#define LongToULongPtr LongToULong +#define LongLongToULongPtr LongLongToULong + +#define IntPtrToULongPtr IntPtrToULong +#define LongPtrToULongPtr LongPtrToULong +#endif + +__inline +HRESULT +ULongLongToULongPtr( + IN ULONGLONG ullOperand, + OUT ULONG_PTR* pulResult) +{ +#ifdef HOST_64BIT + *pulResult = ullOperand; + return S_OK; +#else + return ULongLongToULong(ullOperand, (ULONG*)pulResult); +#endif +} + + +// +// ULONG_PTR -> * conversion (ULONG_PTR is ULONG on Win32, ULONGLONG on Win64) +// +#ifdef HOST_64BIT +#define ULongPtrToUShort ULongLongToUShort +#define ULongPtrToInt ULongLongToInt +#define ULongPtrToLong ULongLongToLong +#define ULongPtrToLongLong ULongLongToLongLong +#define ULongPtrToIntPtr ULongLongToIntPtr +#define ULongPtrToLongPtr ULongLongToLongPtr +#else + +__inline +HRESULT +ULongPtrToUShort( + IN ULONG_PTR ulOperand, + OUT USHORT* pusResult) +{ + return ULongToUShort((ULONG)ulOperand, pusResult); +} + +__inline +HRESULT +ULongPtrToInt( + IN ULONG_PTR ulOperand, + OUT INT* piResult) +{ + return ULongToInt((ULONG)ulOperand, piResult); +} + +__inline +HRESULT +ULongPtrToLong( + IN ULONG_PTR Operand, + OUT LONG* Result) +{ + return ULongToLong((ULONG)Operand, Result); +} + +#define ULongPtrToLongLong ULongToLongLong +#define ULongPtrToIntPtr ULongToIntPtr +#define ULongPtrToLongPtr ULongToLongPtr +#endif + +// +// * -> size_t conversion (size_t is always UINT_PTR) +// +#define CharToSizeT CharToUIntPtr +#define SignedCharToSizeT SignedCharToUIntPtr +#define ShortToSizeT ShortToUIntPtr +#define IntToSizeT IntToUIntPtr +#define LongToSizeT LongToUIntPtr +#define LongLongToSizeT LongLongToUIntPtr +#define ULongLongToSizeT ULongLongToUIntPtr +#define IntPtrToSizeT IntPtrToUIntPtr +#define LongPtrToSizeT LongPtrToUIntPtr + +// +// size_t -> * conversion (size_t is always UINT_PTR) +// +#define SizeTToUShort UIntPtrToUShort +#define SizeTToUInt UIntPtrToUInt +#define SizeTToULong UIntPtrToULong +#define SizeTToInt UIntPtrToInt +#define SizeTToLong UIntPtrToLong +#define SizeTToLongLong UIntPtrToLongLong +#define SizeTToIntPtr UIntPtrToIntPtr +#define SizeTToLongPtr UIntPtrToLongPtr + +// +// * -> SIZE_T conversion (SIZE_T is always ULONG_PTR) +// +#define CharToSIZET CharToULongPtr +#define SignedCharToSIZET SignedCharToULongPtr +#define ShortToSIZET ShortToULongPtr +#define IntToSIZET IntToULongPtr +#define LongToSIZET LongToULongPtr +#define LongLongToSIZET LongLongToULongPtr +#define IntPtrToSIZET IntPtrToULongPtr +#define LongPtrToSIZET LongPtrToULongPtr +#define ULongLongToSIZET ULongLongToULongPtr + +// +// SIZE_T -> * conversion (SIZE_T is always ULONG_PTR) +// +#define SIZETToUShort ULongPtrToUShort +#define SIZETToUInt ULongPtrToUInt +#define SIZETToULong ULongPtrToULong +#define SIZETToUIntPtr ULongPtrToUIntPtr +#define SIZETToULongPtr ULongPtrToULongPtr +#define SIZETToInt ULongPtrToInt +#define SIZETToLong ULongPtrToLong +#define SIZETToLongLong ULongPtrToLongLong +#define SIZETToIntPtr ULongPtrToIntPtr +#define SIZETToLongPtr ULongPtrToLongPtr + +// +// * -> DWORD_PTR conversion (DWORD_PTR is always ULONG_PTR) +// +#define CharToDWordPtr CharToULongPtr +#define SignedCharToDWordPtr SignedCharToULongPtr +#define ShortToDWordPtr ShortToULongPtr +#define IntToDWordPtr IntToULongPtr +#define LongToDWordPtr LongToULongPtr +#define LongLongToDWordPtr LongLongToULongPtr +#define ULongLongToDWordPtr ULongLongToULongPtr +#define IntPtrToDWordPtr IntPtrToULongPtr +#define LongPtrToDWordPtr LongPtrToULongPtr + +// +// DWORD_PTR -> * conversion (DWORD_PTR is always ULONG_PTR) +// +#define DWordPtrToUShort ULongPtrToUShort +#define DWordPtrToUInt ULongPtrToUInt +#define DWordPtrToULong ULongPtrToULong +#define DWordPtrToDWord ULongPtrToDWord +#define DWordPtrToInt ULongPtrToInt +#define DWordPtrToLong ULongPtrToLong +#define DWordPtrToLongLong ULongPtrToLongLong +#define DWordPtrToIntPtr ULongPtrToIntPtr +#define DWordPtrToLongPtr ULongPtrToLongPtr + +// +// USHORT addition +// +__inline +HRESULT +UShortAdd( + IN USHORT usAugend, + IN USHORT usAddend, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (((USHORT)(usAugend + usAddend)) >= usAugend) + { + *pusResult = (usAugend + usAddend); + hr = S_OK; + } + + return hr; +} + +// +// WORD addtition +// +#define WordAdd UShortAdd + +// +// UINT addition +// +__inline +HRESULT +UIntAdd( + IN UINT uAugend, + IN UINT uAddend, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if ((uAugend + uAddend) >= uAugend) + { + *puResult = (uAugend + uAddend); + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR addition +// +#define UIntPtrAdd SizeTAdd + +// +// ULONG addition +// +__inline +HRESULT +ULongAdd( + IN ULONG ulAugend, + IN ULONG ulAddend, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if ((ulAugend + ulAddend) >= ulAugend) + { + *pulResult = (ulAugend + ulAddend); + hr = S_OK; + } + + return hr; +} + +// +// ULONG_PTR addition +// +#ifdef HOST_64BIT +#define ULongPtrAdd ULongLongAdd +#else +__inline +HRESULT +ULongPtrAdd( + IN ULONG_PTR ulAugend, + IN ULONG_PTR ulAddend, + OUT ULONG_PTR* pulResult) +{ + return ULongAdd((ULONG)ulAugend, (ULONG)ulAddend, (ULONG*)pulResult); +} +#endif // HOST_64BIT + +// +// DWORD addition +// +#define DWordAdd ULongAdd + +// +// DWORD_PTR addition +// +#define DWordPtrAdd ULongPtrAdd + +// +// size_t addition +// +__inline +HRESULT +SizeTAdd( + IN size_t Augend, + IN size_t Addend, + OUT size_t* pResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pResult = SIZET_ERROR; + + if ((Augend + Addend) >= Augend) + { + *pResult = (Augend + Addend); + hr = S_OK; + } + + return hr; +} + +// +// SIZE_T addition +// +#define SIZETAdd ULongPtrAdd + +// +// ULONGLONG addition +// +__inline +HRESULT +ULongLongAdd( + IN ULONGLONG ullAugend, + IN ULONGLONG ullAddend, + OUT ULONGLONG* pullResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pullResult = ULONGLONG_ERROR; + + if ((ullAugend + ullAddend) >= ullAugend) + { + *pullResult = (ullAugend + ullAddend); + hr = S_OK; + } + + return hr; +} + +// +// USHORT subtraction +// +__inline +HRESULT +UShortSub( + IN USHORT usMinuend, + IN USHORT usSubtrahend, + OUT USHORT* pusResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pusResult = USHORT_ERROR; + + if (usMinuend >= usSubtrahend) + { + *pusResult = (usMinuend - usSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// WORD subtraction +// +#define WordSub UShortSub + + +// +// UINT subtraction +// +__inline +HRESULT +UIntSub( + IN UINT uMinuend, + IN UINT uSubtrahend, + OUT UINT* puResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *puResult = UINT_ERROR; + + if (uMinuend >= uSubtrahend) + { + *puResult = (uMinuend - uSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// UINT_PTR subtraction +// +#define UIntPtrSub SizeTSub + +// +// ULONG subtraction +// +__inline +HRESULT +ULongSub( + IN ULONG ulMinuend, + IN ULONG ulSubtrahend, + OUT ULONG* pulResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pulResult = ULONG_ERROR; + + if (ulMinuend >= ulSubtrahend) + { + *pulResult = (ulMinuend - ulSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// ULONG_PTR subtraction +// +#ifdef HOST_64BIT +#define ULongPtrSub ULongLongSub +#else +__inline +HRESULT +ULongPtrSub( + IN ULONG_PTR ulMinuend, + IN ULONG_PTR ulSubtrahend, + OUT ULONG_PTR* pulResult) +{ + return ULongSub((ULONG)ulMinuend, (ULONG)ulSubtrahend, (ULONG*)pulResult); +} +#endif // HOST_64BIT + + +// +// DWORD subtraction +// +#define DWordSub ULongSub + +// +// DWORD_PTR subtraction +// +#define DWordPtrSub ULongPtrSub + +// +// size_t subtraction +// +__inline +HRESULT +SizeTSub( + IN size_t Minuend, + IN size_t Subtrahend, + OUT size_t* pResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pResult = SIZET_ERROR; + + if (Minuend >= Subtrahend) + { + *pResult = (Minuend - Subtrahend); + hr = S_OK; + } + + return hr; +} + +// +// SIZE_T subtraction +// +#define SIZETSub ULongPtrSub + +// +// ULONGLONG subtraction +// +__inline +HRESULT +ULongLongSub( + IN ULONGLONG ullMinuend, + IN ULONGLONG ullSubtrahend, + OUT ULONGLONG* pullResult) +{ + HRESULT hr = INTSAFE_E_ARITHMETIC_OVERFLOW; + *pullResult = ULONGLONG_ERROR; + + if (ullMinuend >= ullSubtrahend) + { + *pullResult = (ullMinuend - ullSubtrahend); + hr = S_OK; + } + + return hr; +} + +// +// USHORT multiplication +// +__inline +HRESULT +UShortMult( + IN USHORT usMultiplicand, + IN USHORT usMultiplier, + OUT USHORT* pusResult) +{ + ULONG ulResult = ((ULONG)usMultiplicand) * (ULONG)usMultiplier; + + return ULongToUShort(ulResult, pusResult); +} + +// +// WORD multiplication +// +#define WordMult UShortMult + +// +// UINT multiplication +// +__inline +HRESULT +UIntMult( + IN UINT uMultiplicand, + IN UINT uMultiplier, + OUT UINT* puResult) +{ + ULONGLONG ull64Result = UInt32x32To64(uMultiplicand, uMultiplier); + + return ULongLongToUInt(ull64Result, puResult); +} + +// +// ULONG multiplication +// +__inline +HRESULT +ULongMult( + IN ULONG ulMultiplicand, + IN ULONG ulMultiplier, + OUT ULONG* pulResult) +{ + ULONGLONG ull64Result = UInt32x32To64(ulMultiplicand, ulMultiplier); + + return ULongLongToULong(ull64Result, pulResult); +} + +// +// DWORD multiplication +// +#define DWordMult ULongMult + +// +// DWORD_PTR multiplication +// +#define DWordPtrMult ULongPtrMult + +#endif // _INTSAFE_H_INCLUDED_ diff --git a/src/coreclr/pal/inc/rt/palrt.h b/src/coreclr/pal/inc/rt/palrt.h index 10808247710ac..626422334ef69 100644 --- a/src/coreclr/pal/inc/rt/palrt.h +++ b/src/coreclr/pal/inc/rt/palrt.h @@ -1148,14 +1148,6 @@ typedef struct _DISPATCHER_CONTEXT { DWORD Reserved; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; -#elif defined(HOST_POWERPC64) - -typedef struct _DISPATCHER_CONTEXT { - // PPC64LE does not build the VM or JIT at this point, - // so we only provide a dummy definition. - DWORD Reserved; -} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; - #else #error Unknown architecture for defining DISPATCHER_CONTEXT. diff --git a/src/coreclr/pal/inc/unixasmmacros.inc b/src/coreclr/pal/inc/unixasmmacros.inc index cf05fbe319934..a814c5ab98171 100644 --- a/src/coreclr/pal/inc/unixasmmacros.inc +++ b/src/coreclr/pal/inc/unixasmmacros.inc @@ -19,7 +19,7 @@ #if defined(__APPLE__) #define C_PLTFUNC(name) _##name -#elif defined(HOST_ARM64) || defined(HOST_POWERPC64) +#elif defined(HOST_ARM64) #define C_PLTFUNC(name) name #else #define C_PLTFUNC(name) name@PLT @@ -47,6 +47,4 @@ #include "unixasmmacross390x.inc" #elif defined(HOST_LOONGARCH64) #include "unixasmmacrosloongarch64.inc" -#elif defined(HOST_POWERPC64) -#include "unixasmmacrosppc64le.inc" #endif diff --git a/src/coreclr/pal/inc/unixasmmacrosppc64le.inc b/src/coreclr/pal/inc/unixasmmacrosppc64le.inc deleted file mode 100644 index 2c1c4d6f3e1de..0000000000000 --- a/src/coreclr/pal/inc/unixasmmacrosppc64le.inc +++ /dev/null @@ -1,37 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -.macro NESTED_ENTRY Name, Section, Handler - LEAF_ENTRY \Name, \Section - .ifnc \Handler, NoHandler - .personality C_FUNC(\Handler) - .endif -.endm - -.macro NESTED_END Name, Section - LEAF_END \Name, \Section -.endm - -.macro PATCH_LABEL Name - .global C_FUNC(\Name) -C_FUNC(\Name): -.endm - -.macro LEAF_ENTRY Name, Section - .global C_FUNC(\Name) - .type \Name, %function -C_FUNC(\Name): - .cfi_startproc -.endm - -.macro LEAF_END Name, Section - .size \Name, .-\Name - .cfi_endproc -.endm - -.macro LEAF_END_MARKED Name, Section -C_FUNC(\Name\()_End): - .global C_FUNC(\Name\()_End) - LEAF_END \Name, \Section -.endm - diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 933333aba64a2..4e6509c88590c 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -56,8 +56,6 @@ elseif(CLR_CMAKE_HOST_ARCH_I386) set(PAL_ARCH_SOURCES_DIR i386) elseif(CLR_CMAKE_HOST_ARCH_S390X) set(PAL_ARCH_SOURCES_DIR s390x) -elseif(CLR_CMAKE_HOST_ARCH_POWERPC64) - set(PAL_ARCH_SOURCES_DIR ppc64le) endif() if(CLR_CMAKE_USE_SYSTEM_LIBUNWIND) diff --git a/src/coreclr/pal/src/arch/ppc64le/asmconstants.h b/src/coreclr/pal/src/arch/ppc64le/asmconstants.h deleted file mode 100644 index 15ee945dafaa4..0000000000000 --- a/src/coreclr/pal/src/arch/ppc64le/asmconstants.h +++ /dev/null @@ -1,89 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#ifndef __PAL_POWERPC_ASMCONSTANTS_H__ -#define __PAL_POWERPC_ASMCONSTANTS_H__ - -#define CONTEXT_PPC64 0x100000 - -#define CONTEXT_CONTROL 1 -#define CONTEXT_INTEGER 2 -#define CONTEXT_FLOATING_POINT 4 - -#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT) - -#define CONTEXT_ContextFlags 0 -#define CONTEXT_R0 CONTEXT_ContextFlags+8 -#define CONTEXT_R1 CONTEXT_R0+8 -#define CONTEXT_R2 CONTEXT_R1+8 -#define CONTEXT_R3 CONTEXT_R2+8 -#define CONTEXT_R4 CONTEXT_R3+8 -#define CONTEXT_R5 CONTEXT_R4+8 -#define CONTEXT_R6 CONTEXT_R5+8 -#define CONTEXT_R7 CONTEXT_R6+8 -#define CONTEXT_R8 CONTEXT_R7+8 -#define CONTEXT_R9 CONTEXT_R8+8 -#define CONTEXT_R10 CONTEXT_R9+8 -#define CONTEXT_R11 CONTEXT_R10+8 -#define CONTEXT_R12 CONTEXT_R11+8 -#define CONTEXT_R13 CONTEXT_R12+8 -#define CONTEXT_R14 CONTEXT_R13+8 -#define CONTEXT_R15 CONTEXT_R14+8 -#define CONTEXT_R16 CONTEXT_R15+8 -#define CONTEXT_R17 CONTEXT_R16+8 -#define CONTEXT_R18 CONTEXT_R17+8 -#define CONTEXT_R19 CONTEXT_R18+8 -#define CONTEXT_R20 CONTEXT_R19+8 -#define CONTEXT_R21 CONTEXT_R20+8 -#define CONTEXT_R22 CONTEXT_R21+8 -#define CONTEXT_R23 CONTEXT_R22+8 -#define CONTEXT_R24 CONTEXT_R23+8 -#define CONTEXT_R25 CONTEXT_R24+8 -#define CONTEXT_R26 CONTEXT_R25+8 -#define CONTEXT_R27 CONTEXT_R26+8 -#define CONTEXT_R28 CONTEXT_R27+8 -#define CONTEXT_R29 CONTEXT_R28+8 -#define CONTEXT_R30 CONTEXT_R29+8 -#define CONTEXT_R31 CONTEXT_R30+8 -#define CONTEXT_F0 CONTEXT_R31+8 -#define CONTEXT_F1 CONTEXT_F0+8 -#define CONTEXT_F2 CONTEXT_F1+8 -#define CONTEXT_F3 CONTEXT_F2+8 -#define CONTEXT_F4 CONTEXT_F3+8 -#define CONTEXT_F5 CONTEXT_F4+8 -#define CONTEXT_F6 CONTEXT_F5+8 -#define CONTEXT_F7 CONTEXT_F6+8 -#define CONTEXT_F8 CONTEXT_F7+8 -#define CONTEXT_F9 CONTEXT_F8+8 -#define CONTEXT_F10 CONTEXT_F9+8 -#define CONTEXT_F11 CONTEXT_F10+8 -#define CONTEXT_F12 CONTEXT_F11+8 -#define CONTEXT_F13 CONTEXT_F12+8 -#define CONTEXT_F14 CONTEXT_F13+8 -#define CONTEXT_F15 CONTEXT_F14+8 -#define CONTEXT_F16 CONTEXT_F15+8 -#define CONTEXT_F17 CONTEXT_F16+8 -#define CONTEXT_F18 CONTEXT_F17+8 -#define CONTEXT_F19 CONTEXT_F18+8 -#define CONTEXT_F20 CONTEXT_F19+8 -#define CONTEXT_F21 CONTEXT_F20+8 -#define CONTEXT_F22 CONTEXT_F21+8 -#define CONTEXT_F23 CONTEXT_F22+8 -#define CONTEXT_F24 CONTEXT_F23+8 -#define CONTEXT_F25 CONTEXT_F24+8 -#define CONTEXT_F26 CONTEXT_F25+8 -#define CONTEXT_F27 CONTEXT_F26+8 -#define CONTEXT_F28 CONTEXT_F27+8 -#define CONTEXT_F29 CONTEXT_F28+8 -#define CONTEXT_F30 CONTEXT_F29+8 -#define CONTEXT_F31 CONTEXT_F30+8 -#define CONTEXT_FPSCR CONTEXT_F31+8 -#define CONTEXT_NIP CONTEXT_FPSCR+8 -#define CONTEXT_MSR CONTEXT_NIP+8 -#define CONTEXT_CTR CONTEXT_MSR+8 -#define CONTEXT_LINK CONTEXT_CTR+8 -#define CONTEXT_XER CONTEXT_LINK+8 -#define CONTEXT_CCR CONTEXT_XER+8 -#define CONTEXT_Size CONTEXT_CCR+8 - -#endif diff --git a/src/coreclr/pal/src/arch/ppc64le/callsignalhandlerwrapper.S b/src/coreclr/pal/src/arch/ppc64le/callsignalhandlerwrapper.S deleted file mode 100644 index 1ace1393c3feb..0000000000000 --- a/src/coreclr/pal/src/arch/ppc64le/callsignalhandlerwrapper.S +++ /dev/null @@ -1,31 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "unixasmmacros.inc" -#include "asmconstants.h" - -.macro CALL_SIGNAL_HANDLER_WRAPPER Alignment - -.globl C_FUNC(SignalHandlerWorkerReturnOffset\Alignment) -C_FUNC(SignalHandlerWorkerReturnOffset\Alignment): - .int LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment)-C_FUNC(CallSignalHandlerWrapper\Alignment) - -// This function is never called, only a fake stack frame will be setup to have a return -// address set to SignalHandlerWorkerReturn during SIGSEGV handling. -// It enables the unwinder to unwind stack from the handling code to the actual failure site. -NESTED_ENTRY CallSignalHandlerWrapper\Alignment, _TEXT, NoHandler - mflr %r0 - std %r0, 16(%r1) - stdu %r1,-32(%r1) - bl EXTERNAL_C_FUNC(signal_handler_worker) -LOCAL_LABEL(SignalHandlerWorkerReturn\Alignment): - addi %r1, %r1, 32 - ld %r0, 16(%r1) - mtlr %r0 - blr -NESTED_END CallSignalHandlerWrapper\Alignment, _TEXT - -.endm - -CALL_SIGNAL_HANDLER_WRAPPER 0 -CALL_SIGNAL_HANDLER_WRAPPER 8 diff --git a/src/coreclr/pal/src/arch/ppc64le/context2.S b/src/coreclr/pal/src/arch/ppc64le/context2.S deleted file mode 100644 index f48c7414ae6e6..0000000000000 --- a/src/coreclr/pal/src/arch/ppc64le/context2.S +++ /dev/null @@ -1,188 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// Implementation of _CONTEXT_CaptureContext for the IBM power ppc64le platform. -// This function is processor dependent. It is used by exception handling, -// and is always apply to the current thread. -// - -#include "unixasmmacros.inc" -#include "asmconstants.h" - -// Incoming: -// R3: Context* -// -LEAF_ENTRY CONTEXT_CaptureContext, _TEXT - - // Store all general purpose registers - std %r0, CONTEXT_R0(%r3) - std %r1, CONTEXT_R1(%r3) - std %r2, CONTEXT_R2(%r3) - std %r3, CONTEXT_R3(%r3) - std %r4, CONTEXT_R4(%r3) - std %r5, CONTEXT_R5(%r3) - std %r6, CONTEXT_R6(%r3) - std %r7, CONTEXT_R7(%r3) - std %r8, CONTEXT_R8(%r3) - std %r9, CONTEXT_R9(%r3) - std %r10, CONTEXT_R10(%r3) - std %r11, CONTEXT_R11(%r3) - std %r12, CONTEXT_R12(%r3) - std %r13, CONTEXT_R13(%r3) - std %r14, CONTEXT_R14(%r3) - std %r15, CONTEXT_R15(%r3) - std %r16, CONTEXT_R16(%r3) - std %r17, CONTEXT_R17(%r3) - std %r18, CONTEXT_R18(%r3) - std %r19, CONTEXT_R19(%r3) - std %r20, CONTEXT_R20(%r3) - std %r21, CONTEXT_R21(%r3) - std %r22, CONTEXT_R22(%r3) - std %r23, CONTEXT_R23(%r3) - std %r24, CONTEXT_R24(%r3) - std %r25, CONTEXT_R25(%r3) - std %r26, CONTEXT_R26(%r3) - std %r27, CONTEXT_R27(%r3) - std %r28, CONTEXT_R28(%r3) - std %r29, CONTEXT_R29(%r3) - std %r30, CONTEXT_R30(%r3) - std %r31, CONTEXT_R31(%r3) - - // Store all floating point registers - stfd %f0, CONTEXT_F0(%r3) - stfd %f1, CONTEXT_F1(%r3) - stfd %f2, CONTEXT_F2(%r3) - stfd %f3, CONTEXT_F3(%r3) - stfd %f4, CONTEXT_F4(%r3) - stfd %f5, CONTEXT_F5(%r3) - stfd %f6, CONTEXT_F6(%r3) - stfd %f7, CONTEXT_F7(%r3) - stfd %f8, CONTEXT_F8(%r3) - stfd %f9, CONTEXT_F9(%r3) - stfd %f10, CONTEXT_F10(%r3) - stfd %f11, CONTEXT_F11(%r3) - stfd %f12, CONTEXT_F12(%r3) - stfd %f13, CONTEXT_F13(%r3) - stfd %f14, CONTEXT_F14(%r3) - stfd %f15, CONTEXT_F15(%r3) - stfd %f16, CONTEXT_F16(%r3) - stfd %f17, CONTEXT_F17(%r3) - stfd %f18, CONTEXT_F18(%r3) - stfd %f19, CONTEXT_F19(%r3) - stfd %f20, CONTEXT_F20(%r3) - stfd %f21, CONTEXT_F21(%r3) - stfd %f22, CONTEXT_F22(%r3) - stfd %f23, CONTEXT_F23(%r3) - stfd %f24, CONTEXT_F24(%r3) - stfd %f25, CONTEXT_F25(%r3) - stfd %f26, CONTEXT_F26(%r3) - stfd %f27, CONTEXT_F27(%r3) - stfd %f28, CONTEXT_F28(%r3) - stfd %f29, CONTEXT_F29(%r3) - stfd %f30, CONTEXT_F30(%r3) - stfd %f31, CONTEXT_F31(%r3) - - // Save Control Registers - XER, LR and CTR - mfspr 5, 1 - std %r5, CONTEXT_XER(%r3) - mflr %r5 - std %r5, CONTEXT_LINK(%r3) - mfspr 5, 9 - std %r5, CONTEXT_CTR(%r3) - - // Restore r5 general purpose register - ld %r5, CONTEXT_R5(%r3) - - blr -LEAF_END CONTEXT_CaptureContext, _TEXT - -LEAF_ENTRY RtlCaptureContext, _TEXT - b C_FUNC(CONTEXT_CaptureContext) -LEAF_END RtlCaptureContext, _TEXT - -LEAF_ENTRY RtlRestoreContext, _TEXT - - // Restore all floating point registers - lfd %f0, CONTEXT_F0(%r3) - lfd %f1, CONTEXT_F1(%r3) - lfd %f2, CONTEXT_F2(%r3) - lfd %f3, CONTEXT_F3(%r3) - lfd %f4, CONTEXT_F4(%r3) - lfd %f5, CONTEXT_F5(%r3) - lfd %f6, CONTEXT_F6(%r3) - lfd %f7, CONTEXT_F7(%r3) - lfd %f8, CONTEXT_F8(%r3) - lfd %f9, CONTEXT_F9(%r3) - lfd %f10, CONTEXT_F10(%r3) - lfd %f11, CONTEXT_F11(%r3) - lfd %f12, CONTEXT_F12(%r3) - lfd %f13, CONTEXT_F13(%r3) - lfd %f14, CONTEXT_F14(%r3) - lfd %f15, CONTEXT_F15(%r3) - lfd %f16, CONTEXT_F16(%r3) - lfd %f17, CONTEXT_F17(%r3) - lfd %f18, CONTEXT_F18(%r3) - lfd %f19, CONTEXT_F19(%r3) - lfd %f20, CONTEXT_F20(%r3) - lfd %f21, CONTEXT_F21(%r3) - lfd %f22, CONTEXT_F22(%r3) - lfd %f23, CONTEXT_F23(%r3) - lfd %f24, CONTEXT_F24(%r3) - lfd %f25, CONTEXT_F25(%r3) - lfd %f26, CONTEXT_F26(%r3) - lfd %f27, CONTEXT_F27(%r3) - lfd %f28, CONTEXT_F28(%r3) - lfd %f29, CONTEXT_F29(%r3) - lfd %f30, CONTEXT_F30(%r3) - lfd %f31, CONTEXT_F31(%r3) - - // Restore all general purpose registers - ld %r0, CONTEXT_R0(%R3) - ld %r1, CONTEXT_R1(%r3) - ld %r2, CONTEXT_R2(%r3) - ld %r4, CONTEXT_R4(%r3) - ld %r5, CONTEXT_R5(%r3) - ld %r6, CONTEXT_R6(%r3) - ld %r7, CONTEXT_R7(%r3) - ld %r8, CONTEXT_R8(%r3) - ld %r9, CONTEXT_R9(%r3) - ld %r10, CONTEXT_R10(%r3) - ld %r11, CONTEXT_R11(%r3) - ld %r12, CONTEXT_R12(%r3) - ld %r13, CONTEXT_R13(%r3) - ld %r14, CONTEXT_R14(%r3) - ld %r15, CONTEXT_R15(%r3) - ld %r16, CONTEXT_R16(%r3) - ld %r17, CONTEXT_R17(%r3) - ld %r18, CONTEXT_R18(%r3) - ld %r19, CONTEXT_R19(%r3) - ld %r20, CONTEXT_R20(%r3) - ld %r21, CONTEXT_R21(%r3) - ld %r22, CONTEXT_R22(%r3) - ld %r23, CONTEXT_R23(%r3) - ld %r24, CONTEXT_R24(%r3) - ld %r25, CONTEXT_R25(%r3) - ld %r26, CONTEXT_R26(%r3) - ld %r27, CONTEXT_R27(%r3) - ld %r28, CONTEXT_R28(%r3) - ld %r29, CONTEXT_R29(%r3) - ld %r30, CONTEXT_R30(%r3) - ld %r31, CONTEXT_R31(%r3) - - // Restore Control Register - XER - ld %r12, CONTEXT_XER(%r3) - mtspr 1, 12 - - // Restore Control Register - LR - mtlr %r0 - - // Restore Control Register - CTR - ld %r12, CONTEXT_LINK(%r3) - mtctr %r12 - - // Restore R3 register - ld %r3, CONTEXT_R3(%r3) - - // Branch to CTR register location - bctr -LEAF_END RtlRestoreContext, _TEXT diff --git a/src/coreclr/pal/src/arch/ppc64le/debugbreak.S b/src/coreclr/pal/src/arch/ppc64le/debugbreak.S deleted file mode 100644 index 8ff9c9c40cf7c..0000000000000 --- a/src/coreclr/pal/src/arch/ppc64le/debugbreak.S +++ /dev/null @@ -1,10 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "unixasmmacros.inc" - -LEAF_ENTRY DBG_DebugBreak, _TEXT - bl abort - nop -LEAF_END_MARKED DBG_DebugBreak, _TEXT - diff --git a/src/coreclr/pal/src/arch/ppc64le/exceptionhelper.S b/src/coreclr/pal/src/arch/ppc64le/exceptionhelper.S deleted file mode 100644 index 9c3d9f4881aec..0000000000000 --- a/src/coreclr/pal/src/arch/ppc64le/exceptionhelper.S +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "unixasmmacros.inc" -#include "asmconstants.h" - -////////////////////////////////////////////////////////////////////////// -// -// This function creates a stack frame right below the target frame, restores all callee -// saved registers from the passed in context, sets R15 to that frame and sets the -// return address to the target frame's PSW address. -// Then it uses the ThrowExceptionHelper to throw the passed in exception from that context. -// EXTERN_C void ThrowExceptionFromContextInternal(CONTEXT* context, PAL_SEHException* ex); -LEAF_ENTRY ThrowExceptionFromContextInternal, _TEXT - - // Restore all non volatile floating point registers - lfd %f15, CONTEXT_F15(%r3) - lfd %f16, CONTEXT_F16(%r3) - lfd %f17, CONTEXT_F17(%r3) - lfd %f18, CONTEXT_F18(%r3) - lfd %f19, CONTEXT_F19(%r3) - lfd %f20, CONTEXT_F20(%r3) - lfd %f21, CONTEXT_F21(%r3) - lfd %f22, CONTEXT_F22(%r3) - lfd %f23, CONTEXT_F23(%r3) - lfd %f24, CONTEXT_F24(%r3) - lfd %f25, CONTEXT_F25(%r3) - lfd %f26, CONTEXT_F26(%r3) - lfd %f27, CONTEXT_F27(%r3) - lfd %f28, CONTEXT_F28(%r3) - lfd %f29, CONTEXT_F29(%r3) - lfd %f30, CONTEXT_F30(%r3) - lfd %f31, CONTEXT_F31(%r3) - - // Restore all non volatile general purpose registers - ld %r14, CONTEXT_R14(%r3) - ld %r15, CONTEXT_R15(%r3) - ld %r16, CONTEXT_R16(%r3) - ld %r17, CONTEXT_R17(%r3) - ld %r18, CONTEXT_R18(%r3) - ld %r19, CONTEXT_R19(%r3) - ld %r20, CONTEXT_R20(%r3) - ld %r21, CONTEXT_R21(%r3) - ld %r22, CONTEXT_R22(%r3) - ld %r23, CONTEXT_R23(%r3) - ld %r24, CONTEXT_R24(%r3) - ld %r25, CONTEXT_R25(%r3) - ld %r26, CONTEXT_R26(%r3) - ld %r27, CONTEXT_R27(%r3) - ld %r28, CONTEXT_R28(%r3) - ld %r29, CONTEXT_R29(%r3) - ld %r30, CONTEXT_R30(%r3) - ld %r31, CONTEXT_R31(%r3) - - ld %r0, CONTEXT_NIP(%r3) - mtlr %r0 - - ld %r1, CONTEXT_R1(%r3) - - // The PAL_SEHException pointer - mr %r3, %r4 - b EXTERNAL_C_FUNC(ThrowExceptionHelper) -LEAF_END ThrowExceptionFromContextInternal, _TEXT diff --git a/src/coreclr/pal/src/arch/ppc64le/processor.cpp b/src/coreclr/pal/src/arch/ppc64le/processor.cpp deleted file mode 100644 index 6680dbc532677..0000000000000 --- a/src/coreclr/pal/src/arch/ppc64le/processor.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*++ - - - -Module Name: - - processor.cpp - -Abstract: - - Implementation of processor related functions for the IBM PowerPC (ppc64le) - platforms. These functions are processor dependent. - - - ---*/ - -#include "pal/palinternal.h" diff --git a/src/coreclr/pal/src/arch/ppc64le/signalhandlerhelper.cpp b/src/coreclr/pal/src/arch/ppc64le/signalhandlerhelper.cpp deleted file mode 100644 index 66615176a3ad4..0000000000000 --- a/src/coreclr/pal/src/arch/ppc64le/signalhandlerhelper.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include "pal/dbgmsg.h" -SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do this first - -#include "pal/palinternal.h" -#include "pal/context.h" -#include "pal/signal.hpp" -#include "pal/utils.h" -#include - -/*++ -Function : - ExecuteHandlerOnCustomStack - - Execute signal handler on a custom stack, the current stack pointer is specified by the customSp - If the customSp is 0, then the handler is executed on the original stack where the signal was fired. - It installs a fake stack frame to enable stack unwinding to the signal source location. - -Parameters : - POSIX signal handler parameter list ("man sigaction" for details) - returnPoint - context to which the function returns if the common_signal_handler returns - - (no return value) ---*/ -void ExecuteHandlerOnCustomStack(int code, siginfo_t *siginfo, void *context, size_t customSp, SignalHandlerWorkerReturnPoint* returnPoint) -{ - ucontext_t *ucontext = (ucontext_t *)context; - size_t faultSp = (size_t)MCREG_R1(ucontext->uc_mcontext); - _ASSERTE(IS_ALIGNED(faultSp, 8)); - - if (customSp == 0) - { - customSp = faultSp; - } - - size_t fakeFrameReturnAddress; - if (IS_ALIGNED(faultSp, 16)) - { - fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset0 + (size_t)CallSignalHandlerWrapper0; - } - else - { - fakeFrameReturnAddress = (size_t)SignalHandlerWorkerReturnOffset8 + (size_t)CallSignalHandlerWrapper8; - } - - // Build fake stack frame to enable the stack unwinder to unwind from signal_handler_worker to the faulting instruction - size_t* saveArea = (size_t*)(customSp - 32); - saveArea[0] = faultSp; - saveArea[2] = (size_t)MCREG_Nip(ucontext->uc_mcontext); - size_t sp = customSp - 32; - - // Switch the current context to the signal_handler_worker and the custom stack - CONTEXT context2; - RtlCaptureContext(&context2); - - context2.Link = (size_t)signal_handler_worker; - context2.R0 = fakeFrameReturnAddress; - context2.R1 = sp; - context2.R3 = code; - context2.R4 = (size_t)siginfo; - context2.R5 = (size_t)context; - context2.R6 = (size_t)returnPoint; - - - RtlRestoreContext(&context2, NULL); -} diff --git a/src/coreclr/pal/src/cruntime/file.cpp b/src/coreclr/pal/src/cruntime/file.cpp index 70462122c10a2..eb2512c68e0e3 100644 --- a/src/coreclr/pal/src/cruntime/file.cpp +++ b/src/coreclr/pal/src/cruntime/file.cpp @@ -522,7 +522,7 @@ PAL_fread(void * buffer, size_t size, size_t count, PAL_FILE * f) } else { - temp[nCount++]= (char)nChar; + temp[nCount++]=nChar; } } } diff --git a/src/coreclr/pal/src/cruntime/printf.cpp b/src/coreclr/pal/src/cruntime/printf.cpp index c312a935656f9..00c7d70c8af58 100644 --- a/src/coreclr/pal/src/cruntime/printf.cpp +++ b/src/coreclr/pal/src/cruntime/printf.cpp @@ -265,7 +265,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, if (*Fmt && **Fmt == '%') { - *Out++ = (CHAR)*(*Fmt)++; + *Out++ = *(*Fmt)++; } else { @@ -285,7 +285,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, if (**Fmt == '*') { *Store = FALSE; - *Out++ = (CHAR)*(*Fmt)++; + *Out++ = *(*Fmt)++; } /* grab width specifier */ @@ -294,8 +294,8 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, TempStrPtr = TempStr; while (isdigit(**Fmt)) { - *TempStrPtr++ = (CHAR)**Fmt; - *Out++ = (CHAR)*(*Fmt)++; + *TempStrPtr++ = **Fmt; + *Out++ = *(*Fmt)++; } *TempStrPtr = 0; /* end string */ *Width = atoi(TempStr); @@ -406,7 +406,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, Out += strlen(scanf_longlongfmt); } - *Out++ = (CHAR)*(*Fmt)++; + *Out++ = *(*Fmt)++; Result = TRUE; } else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' || @@ -416,7 +416,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, *Type = SCANF_TYPE_FLOAT; /* this gets rid of %E/%G since they're they're the same when scanning */ - *Out++ = (CHAR)tolower( *(*Fmt)++ ); + *Out++ = tolower( *(*Fmt)++ ); Result = TRUE; } else if (**Fmt == 'n') @@ -425,7 +425,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, { *Out++ = 'h'; } - *Out++ = (CHAR)*(*Fmt)++; + *Out++ = *(*Fmt)++; *Type = SCANF_TYPE_N; Result = TRUE; } @@ -489,8 +489,8 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, unsigned char prev, next; /* get the interval boundaries */ - prev = (unsigned char)(*Fmt)[-1]; - next = (unsigned char)(*Fmt)[1]; + prev = (*Fmt)[-1]; + next = (*Fmt)[1]; /* if boundaries were inverted, replace the already-copied low boundary by the 'real' low boundary */ @@ -514,7 +514,7 @@ static BOOL Internal_ScanfExtractFormatW(LPCWSTR *Fmt, LPSTR Out, int iOutSize, else { /* plain character; just copy it */ - *Out++ = (CHAR)**Fmt; + *Out++ = **Fmt; (*Fmt)++; } } @@ -625,7 +625,7 @@ int PAL_wvsscanf(LPCWSTR Buffer, LPCWSTR Format, va_list ap) { if (Prefix == SCANF_PREFIX_SHORT) { - *(va_arg(ap, short *)) = (short)(Buff - Buffer); + *(va_arg(ap, short *)) = Buff - Buffer; } else { diff --git a/src/coreclr/pal/src/cruntime/printfcpp.cpp b/src/coreclr/pal/src/cruntime/printfcpp.cpp index ae37ffbf1a27a..e014fe015e21f 100644 --- a/src/coreclr/pal/src/cruntime/printfcpp.cpp +++ b/src/coreclr/pal/src/cruntime/printfcpp.cpp @@ -706,7 +706,7 @@ BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *Fmt, LPSTR Out, L *Out++ = 'l'; *Out++ = 'l'; } - *Out++ = (CHAR)*(*Fmt)++; + *Out++ = *(*Fmt)++; Result = TRUE; } else if (**Fmt == 'e' || **Fmt == 'E' || **Fmt == 'f' || @@ -719,7 +719,7 @@ BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *Fmt, LPSTR Out, L } *Type = PFF_TYPE_FLOAT; - *Out++ = (CHAR)*(*Fmt)++; + *Out++ = *(*Fmt)++; Result = TRUE; } else if (**Fmt == 'n') @@ -733,7 +733,7 @@ BOOL Internal_ExtractFormatW(CPalThread *pthrCurrent, LPCWSTR *Fmt, LPSTR Out, L { *Out++ = 'h'; } - *Out++ = (CHAR)*(*Fmt)++; + *Out++ = *(*Fmt)++; *Type = PFF_TYPE_N; Result = TRUE; } @@ -1220,8 +1220,8 @@ int CoreVfwprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const wchar_16 *for TempInt = va_arg(ap, INT); /* value not used */ } - TempWChar[0] = (WCHAR)va_arg(ap, int); - TempWChar[1] = W('\0'); + TempWChar[0] = va_arg(ap, int); + TempWChar[1] = 0; /* do the padding (if needed)*/ paddingReturnValue = @@ -1254,7 +1254,7 @@ int CoreVfwprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const wchar_16 *for if (Prefix == PFF_PREFIX_SHORT) { - *(va_arg(ap, short *)) = (short)written; + *(va_arg(ap, short *)) = written; } else { @@ -1605,7 +1605,7 @@ int CoreVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const char *format, TempInt = va_arg(ap, INT); /* value not used */ } - TempWChar = (WCHAR)va_arg(ap, int); + TempWChar = va_arg(ap, int); Length = WideCharToMultiByte(CP_ACP, 0, &TempWChar, 1, TempBuffer, sizeof(TempBuffer), 0, 0); @@ -1617,7 +1617,7 @@ int CoreVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const char *format, va_end(ap); return -1; } - TempBuffer[Length] = W('\0'); + TempBuffer[Length] = 0; /* do the padding (if needed)*/ paddingReturnValue = @@ -1648,7 +1648,7 @@ int CoreVfprintf(CPalThread *pthrCurrent, PAL_FILE *stream, const char *format, if (Prefix == PFF_PREFIX_SHORT) { - *(va_arg(ap, short *)) = (short)written; + *(va_arg(ap, short *)) = written; } else { diff --git a/src/coreclr/pal/src/cruntime/silent_printf.cpp b/src/coreclr/pal/src/cruntime/silent_printf.cpp index 05a0e85906c81..17e3007c762fc 100644 --- a/src/coreclr/pal/src/cruntime/silent_printf.cpp +++ b/src/coreclr/pal/src/cruntime/silent_printf.cpp @@ -168,7 +168,7 @@ int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) TempInt = va_arg(ap, INT); /* value not used */ } - TempWChar = (WCHAR)va_arg(ap, int); + TempWChar = va_arg(ap, int); Length = Silent_WideCharToMultiByte(&TempWChar, 1, TempBuffer, 4); if (!Length) { @@ -204,7 +204,7 @@ int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list aparg) if (Prefix == PFF_PREFIX_SHORT) { - *(va_arg(ap, short *)) = (short)written; + *(va_arg(ap, short *)) = written; } else { diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp index ebeb466d66feb..514851fa2244e 100644 --- a/src/coreclr/pal/src/exception/remote-unwind.cpp +++ b/src/coreclr/pal/src/exception/remote-unwind.cpp @@ -124,7 +124,7 @@ typedef BOOL(*UnwindReadMemoryCallback)(PVOID address, PVOID buffer, SIZE_T size #define PRId PRId32 #define PRIA "08" #define PRIxA PRIA PRIx -#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) || defined(TARGET_POWERPC64) +#elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) #define PRIx PRIx64 #define PRIu PRIu64 #define PRId PRId64 @@ -1872,25 +1872,6 @@ static void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, GetContextPointer(cursor, unwContext, UNW_S390X_R13, &contextPointers->R13); GetContextPointer(cursor, unwContext, UNW_S390X_R14, &contextPointers->R14); GetContextPointer(cursor, unwContext, UNW_S390X_R15, &contextPointers->R15); -#elif defined(TARGET_POWERPC64) - GetContextPointer(cursor, unwContext, UNW_PPC64_R14, &contextPointers->R14); - GetContextPointer(cursor, unwContext, UNW_PPC64_R15, &contextPointers->R15); - GetContextPointer(cursor, unwContext, UNW_PPC64_R16, &contextPointers->R16); - GetContextPointer(cursor, unwContext, UNW_PPC64_R17, &contextPointers->R17); - GetContextPointer(cursor, unwContext, UNW_PPC64_R18, &contextPointers->R18); - GetContextPointer(cursor, unwContext, UNW_PPC64_R19, &contextPointers->R19); - GetContextPointer(cursor, unwContext, UNW_PPC64_R20, &contextPointers->R20); - GetContextPointer(cursor, unwContext, UNW_PPC64_R21, &contextPointers->R21); - GetContextPointer(cursor, unwContext, UNW_PPC64_R22, &contextPointers->R22); - GetContextPointer(cursor, unwContext, UNW_PPC64_R23, &contextPointers->R23); - GetContextPointer(cursor, unwContext, UNW_PPC64_R24, &contextPointers->R24); - GetContextPointer(cursor, unwContext, UNW_PPC64_R25, &contextPointers->R25); - GetContextPointer(cursor, unwContext, UNW_PPC64_R26, &contextPointers->R26); - GetContextPointer(cursor, unwContext, UNW_PPC64_R27, &contextPointers->R27); - GetContextPointer(cursor, unwContext, UNW_PPC64_R28, &contextPointers->R28); - GetContextPointer(cursor, unwContext, UNW_PPC64_R29, &contextPointers->R29); - GetContextPointer(cursor, unwContext, UNW_PPC64_R30, &contextPointers->R30); - GetContextPointer(cursor, unwContext, UNW_PPC64_R31, &contextPointers->R31); #else #error unsupported architecture #endif @@ -1978,27 +1959,6 @@ static void UnwindContextToContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_S390X_R13, (unw_word_t *) &winContext->R13); unw_get_reg(cursor, UNW_S390X_R14, (unw_word_t *) &winContext->R14); TRACE("sp %p pc %p lr %p\n", winContext->R15, winContext->PSWAddr, winContext->R14); -#elif defined(TARGET_POWERPC64) - //TODO - unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Nip); - unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->R31); - unw_get_reg(cursor, UNW_PPC64_R14, (unw_word_t *) &winContext->R14); - unw_get_reg(cursor, UNW_PPC64_R15, (unw_word_t *) &winContext->R15); - unw_get_reg(cursor, UNW_PPC64_R16, (unw_word_t *) &winContext->R16); - unw_get_reg(cursor, UNW_PPC64_R17, (unw_word_t *) &winContext->R17); - unw_get_reg(cursor, UNW_PPC64_R18, (unw_word_t *) &winContext->R18); - unw_get_reg(cursor, UNW_PPC64_R19, (unw_word_t *) &winContext->R19); - unw_get_reg(cursor, UNW_PPC64_R20, (unw_word_t *) &winContext->R20); - unw_get_reg(cursor, UNW_PPC64_R21, (unw_word_t *) &winContext->R21); - unw_get_reg(cursor, UNW_PPC64_R22, (unw_word_t *) &winContext->R22); - unw_get_reg(cursor, UNW_PPC64_R23, (unw_word_t *) &winContext->R23); - unw_get_reg(cursor, UNW_PPC64_R24, (unw_word_t *) &winContext->R24); - unw_get_reg(cursor, UNW_PPC64_R25, (unw_word_t *) &winContext->R25); - unw_get_reg(cursor, UNW_PPC64_R26, (unw_word_t *) &winContext->R26); - unw_get_reg(cursor, UNW_PPC64_R27, (unw_word_t *) &winContext->R27); - unw_get_reg(cursor, UNW_PPC64_R28, (unw_word_t *) &winContext->R28); - unw_get_reg(cursor, UNW_PPC64_R29, (unw_word_t *) &winContext->R29); - unw_get_reg(cursor, UNW_PPC64_R30, (unw_word_t *) &winContext->R30); #else #error unsupported architecture #endif @@ -2113,27 +2073,6 @@ access_reg(unw_addr_space_t as, unw_regnum_t regnum, unw_word_t *valp, int write case UNW_S390X_R14: *valp = (unw_word_t)winContext->R14; break; case UNW_S390X_R15: *valp = (unw_word_t)winContext->R15; break; case UNW_S390X_IP: *valp = (unw_word_t)winContext->PSWAddr; break; -#elif defined(TARGET_POWERPC64) - //TODO - case UNW_PPC64_R14: *valp = (unw_word_t)winContext->R14; break; - case UNW_PPC64_R15: *valp = (unw_word_t)winContext->R15; break; - case UNW_PPC64_R16: *valp = (unw_word_t)winContext->R16; break; - case UNW_PPC64_R17: *valp = (unw_word_t)winContext->R17; break; - case UNW_PPC64_R18: *valp = (unw_word_t)winContext->R18; break; - case UNW_PPC64_R19: *valp = (unw_word_t)winContext->R19; break; - case UNW_PPC64_R20: *valp = (unw_word_t)winContext->R20; break; - case UNW_PPC64_R21: *valp = (unw_word_t)winContext->R21; break; - case UNW_PPC64_R22: *valp = (unw_word_t)winContext->R22; break; - case UNW_PPC64_R23: *valp = (unw_word_t)winContext->R23; break; - case UNW_PPC64_R24: *valp = (unw_word_t)winContext->R24; break; - case UNW_PPC64_R25: *valp = (unw_word_t)winContext->R25; break; - case UNW_PPC64_R26: *valp = (unw_word_t)winContext->R26; break; - case UNW_PPC64_R27: *valp = (unw_word_t)winContext->R27; break; - case UNW_PPC64_R28: *valp = (unw_word_t)winContext->R28; break; - case UNW_PPC64_R29: *valp = (unw_word_t)winContext->R29; break; - case UNW_PPC64_R30: *valp = (unw_word_t)winContext->R30; break; - case UNW_PPC64_R31: *valp = (unw_word_t)winContext->R31; break; - case UNW_PPC64_NIP: *valp = (unw_word_t)winContext->Nip; break; #else #error unsupported architecture #endif diff --git a/src/coreclr/pal/src/exception/seh-unwind.cpp b/src/coreclr/pal/src/exception/seh-unwind.cpp index 9fe6c61d0f828..fd9756dffa31b 100644 --- a/src/coreclr/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/pal/src/exception/seh-unwind.cpp @@ -152,27 +152,6 @@ enum ASSIGN_REG(S6) \ ASSIGN_REG(S7) \ ASSIGN_REG(S8) -#elif (defined(HOST_UNIX) && defined(HOST_POWERPC64)) -#define ASSIGN_UNWIND_REGS \ - ASSIGN_REG(Nip) \ - ASSIGN_REG(R14) \ - ASSIGN_REG(R15) \ - ASSIGN_REG(R16) \ - ASSIGN_REG(R17) \ - ASSIGN_REG(R18) \ - ASSIGN_REG(R19) \ - ASSIGN_REG(R20) \ - ASSIGN_REG(R21) \ - ASSIGN_REG(R22) \ - ASSIGN_REG(R23) \ - ASSIGN_REG(R24) \ - ASSIGN_REG(R25) \ - ASSIGN_REG(R26) \ - ASSIGN_REG(R27) \ - ASSIGN_REG(R28) \ - ASSIGN_REG(R29) \ - ASSIGN_REG(R30) \ - ASSIGN_REG(R31) #else #error unsupported architecture #endif @@ -411,26 +390,6 @@ void UnwindContextToWinContext(unw_cursor_t *cursor, CONTEXT *winContext) unw_get_reg(cursor, UNW_LOONGARCH64_R29, (unw_word_t *) &winContext->S6); unw_get_reg(cursor, UNW_LOONGARCH64_R30, (unw_word_t *) &winContext->S7); unw_get_reg(cursor, UNW_LOONGARCH64_R31, (unw_word_t *) &winContext->S8); -#elif (defined(HOST_UNIX) && defined(HOST_POWERPC64)) - unw_get_reg(cursor, UNW_REG_SP, (unw_word_t *) &winContext->R31); - unw_get_reg(cursor, UNW_REG_IP, (unw_word_t *) &winContext->Nip); - unw_get_reg(cursor, UNW_PPC64_R14, (unw_word_t *) &winContext->R14); - unw_get_reg(cursor, UNW_PPC64_R15, (unw_word_t *) &winContext->R15); - unw_get_reg(cursor, UNW_PPC64_R16, (unw_word_t *) &winContext->R16); - unw_get_reg(cursor, UNW_PPC64_R17, (unw_word_t *) &winContext->R17); - unw_get_reg(cursor, UNW_PPC64_R18, (unw_word_t *) &winContext->R18); - unw_get_reg(cursor, UNW_PPC64_R19, (unw_word_t *) &winContext->R19); - unw_get_reg(cursor, UNW_PPC64_R20, (unw_word_t *) &winContext->R20); - unw_get_reg(cursor, UNW_PPC64_R21, (unw_word_t *) &winContext->R21); - unw_get_reg(cursor, UNW_PPC64_R22, (unw_word_t *) &winContext->R22); - unw_get_reg(cursor, UNW_PPC64_R23, (unw_word_t *) &winContext->R23); - unw_get_reg(cursor, UNW_PPC64_R24, (unw_word_t *) &winContext->R24); - unw_get_reg(cursor, UNW_PPC64_R25, (unw_word_t *) &winContext->R25); - unw_get_reg(cursor, UNW_PPC64_R26, (unw_word_t *) &winContext->R26); - unw_get_reg(cursor, UNW_PPC64_R27, (unw_word_t *) &winContext->R27); - unw_get_reg(cursor, UNW_PPC64_R28, (unw_word_t *) &winContext->R28); - unw_get_reg(cursor, UNW_PPC64_R29, (unw_word_t *) &winContext->R29); - unw_get_reg(cursor, UNW_PPC64_R30, (unw_word_t *) &winContext->R30); #else #error unsupported architecture #endif @@ -529,25 +488,6 @@ void GetContextPointers(unw_cursor_t *cursor, unw_context_t *unwContext, KNONVOL GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R29, &contextPointers->S6); GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R30, &contextPointers->S7); GetContextPointer(cursor, unwContext, UNW_LOONGARCH64_R31, &contextPointers->S8); -#elif (defined(HOST_UNIX) && defined(HOST_POWERPC64)) - GetContextPointer(cursor, unwContext, UNW_PPC64_R14, &contextPointers->R14); - GetContextPointer(cursor, unwContext, UNW_PPC64_R15, &contextPointers->R15); - GetContextPointer(cursor, unwContext, UNW_PPC64_R16, &contextPointers->R16); - GetContextPointer(cursor, unwContext, UNW_PPC64_R17, &contextPointers->R17); - GetContextPointer(cursor, unwContext, UNW_PPC64_R18, &contextPointers->R18); - GetContextPointer(cursor, unwContext, UNW_PPC64_R19, &contextPointers->R19); - GetContextPointer(cursor, unwContext, UNW_PPC64_R20, &contextPointers->R20); - GetContextPointer(cursor, unwContext, UNW_PPC64_R21, &contextPointers->R21); - GetContextPointer(cursor, unwContext, UNW_PPC64_R22, &contextPointers->R22); - GetContextPointer(cursor, unwContext, UNW_PPC64_R23, &contextPointers->R23); - GetContextPointer(cursor, unwContext, UNW_PPC64_R24, &contextPointers->R24); - GetContextPointer(cursor, unwContext, UNW_PPC64_R25, &contextPointers->R25); - GetContextPointer(cursor, unwContext, UNW_PPC64_R26, &contextPointers->R26); - GetContextPointer(cursor, unwContext, UNW_PPC64_R27, &contextPointers->R27); - GetContextPointer(cursor, unwContext, UNW_PPC64_R28, &contextPointers->R28); - GetContextPointer(cursor, unwContext, UNW_PPC64_R29, &contextPointers->R29); - GetContextPointer(cursor, unwContext, UNW_PPC64_R30, &contextPointers->R30); - GetContextPointer(cursor, unwContext, UNW_PPC64_R31, &contextPointers->R31); #else #error unsupported architecture #endif diff --git a/src/coreclr/pal/src/file/filetime.cpp b/src/coreclr/pal/src/file/filetime.cpp index ea8ca6bd0535a..768ee426c4dbf 100644 --- a/src/coreclr/pal/src/file/filetime.cpp +++ b/src/coreclr/pal/src/file/filetime.cpp @@ -294,16 +294,16 @@ BOOL PALAPI FileTimeToSystemTime( CONST FILETIME * lpFileTime, #endif /* HAVE_GMTIME_R */ /* Convert unix system time to Windows system time. */ - lpSystemTime->wDay = (WORD)UnixSystemTime->tm_mday; + lpSystemTime->wDay = UnixSystemTime->tm_mday; /* Unix time counts January as a 0, under Windows it is 1*/ - lpSystemTime->wMonth = (WORD)UnixSystemTime->tm_mon + 1; + lpSystemTime->wMonth = UnixSystemTime->tm_mon + 1; /* Unix time returns the year - 1900, Windows returns the current year*/ - lpSystemTime->wYear = (WORD)UnixSystemTime->tm_year + 1900; + lpSystemTime->wYear = UnixSystemTime->tm_year + 1900; - lpSystemTime->wSecond = (WORD)UnixSystemTime->tm_sec; - lpSystemTime->wMinute = (WORD)UnixSystemTime->tm_min; - lpSystemTime->wHour = (WORD)UnixSystemTime->tm_hour; + lpSystemTime->wSecond = UnixSystemTime->tm_sec; + lpSystemTime->wMinute = UnixSystemTime->tm_min; + lpSystemTime->wHour = UnixSystemTime->tm_hour; return TRUE; } else diff --git a/src/coreclr/pal/src/include/pal/context.h b/src/coreclr/pal/src/include/pal/context.h index fec5139fd5e40..fd37f92693c41 100644 --- a/src/coreclr/pal/src/include/pal/context.h +++ b/src/coreclr/pal/src/include/pal/context.h @@ -75,47 +75,6 @@ using asm_sigcontext::_xstate; #define MCREG_R14(mc) ((mc).gregs[14]) #define MCREG_R15(mc) ((mc).gregs[15]) -#elif HOST_POWERPC64 - -#define MCREG_R0(mc) ((mc).gp_regs[0]) -#define MCREG_R1(mc) ((mc).gp_regs[1]) -#define MCREG_R2(mc) ((mc).gp_regs[2]) -#define MCREG_R3(mc) ((mc).gp_regs[3]) -#define MCREG_R4(mc) ((mc).gp_regs[4]) -#define MCREG_R5(mc) ((mc).gp_regs[5]) -#define MCREG_R6(mc) ((mc).gp_regs[6]) -#define MCREG_R7(mc) ((mc).gp_regs[7]) -#define MCREG_R8(mc) ((mc).gp_regs[8]) -#define MCREG_R9(mc) ((mc).gp_regs[9]) -#define MCREG_R10(mc) ((mc).gp_regs[10]) -#define MCREG_R11(mc) ((mc).gp_regs[11]) -#define MCREG_R12(mc) ((mc).gp_regs[12]) -#define MCREG_R13(mc) ((mc).gp_regs[13]) -#define MCREG_R14(mc) ((mc).gp_regs[14]) -#define MCREG_R15(mc) ((mc).gp_regs[15]) -#define MCREG_R16(mc) ((mc).gp_regs[16]) -#define MCREG_R17(mc) ((mc).gp_regs[17]) -#define MCREG_R18(mc) ((mc).gp_regs[18]) -#define MCREG_R19(mc) ((mc).gp_regs[19]) -#define MCREG_R20(mc) ((mc).gp_regs[20]) -#define MCREG_R21(mc) ((mc).gp_regs[21]) -#define MCREG_R22(mc) ((mc).gp_regs[22]) -#define MCREG_R23(mc) ((mc).gp_regs[23]) -#define MCREG_R24(mc) ((mc).gp_regs[24]) -#define MCREG_R25(mc) ((mc).gp_regs[25]) -#define MCREG_R26(mc) ((mc).gp_regs[26]) -#define MCREG_R27(mc) ((mc).gp_regs[27]) -#define MCREG_R28(mc) ((mc).gp_regs[28]) -#define MCREG_R29(mc) ((mc).gp_regs[29]) -#define MCREG_R30(mc) ((mc).gp_regs[30]) -#define MCREG_R31(mc) ((mc).gp_regs[31]) -#define MCREG_Nip(mc) ((mc).gp_regs[32]) -#define MCREG_Msr(mc) ((mc).gp_regs[33]) -#define MCREG_Ctr(mc) ((mc).gp_regs[35]) -#define MCREG_Link(mc) ((mc).gp_regs[36]) -#define MCREG_Xer(mc) ((mc).gp_regs[37]) -#define MCREG_Ccr(mc) ((mc).gp_regs[38]) - #elif HAVE___GREGSET_T #ifdef HOST_64BIT @@ -797,47 +756,6 @@ const VfpSigFrame* GetConstNativeSigSimdContext(const native_context_t *mc) #define PTREG_Pc(ptreg) ((ptreg).csr_epc) #endif // HOST_LOONGARCH64 -#if defined(HOST_POWERPC64) -#define PTREG_R0(ptreg) ((ptreg).gpr[0]) -#define PTREG_R1(ptreg) ((ptreg).gpr[1]) -#define PTREG_R2(ptreg) ((ptreg).gpr[2]) -#define PTREG_R3(ptreg) ((ptreg).gpr[3]) -#define PTREG_R4(ptreg) ((ptreg).gpr[4]) -#define PTREG_R5(ptreg) ((ptreg).gpr[5]) -#define PTREG_R6(ptreg) ((ptreg).gpr[6]) -#define PTREG_R7(ptreg) ((ptreg).gpr[7]) -#define PTREG_R8(ptreg) ((ptreg).gpr[8]) -#define PTREG_R9(ptreg) ((ptreg).gpr[9]) -#define PTREG_R10(ptreg) ((ptreg).gpr[10]) -#define PTREG_R11(ptreg) ((ptreg).gpr[11]) -#define PTREG_R12(ptreg) ((ptreg).gpr[12]) -#define PTREG_R13(ptreg) ((ptreg).gpr[13]) -#define PTREG_R14(ptreg) ((ptreg).gpr[14]) -#define PTREG_R15(ptreg) ((ptreg).gpr[15]) -#define PTREG_R16(ptreg) ((ptreg).gpr[16]) -#define PTREG_R17(ptreg) ((ptreg).gpr[17]) -#define PTREG_R18(ptreg) ((ptreg).gpr[18]) -#define PTREG_R19(ptreg) ((ptreg).gpr[19]) -#define PTREG_R20(ptreg) ((ptreg).gpr[20]) -#define PTREG_R21(ptreg) ((ptreg).gpr[21]) -#define PTREG_R22(ptreg) ((ptreg).gpr[22]) -#define PTREG_R23(ptreg) ((ptreg).gpr[23]) -#define PTREG_R24(ptreg) ((ptreg).gpr[24]) -#define PTREG_R25(ptreg) ((ptreg).gpr[25]) -#define PTREG_R26(ptreg) ((ptreg).gpr[26]) -#define PTREG_R27(ptreg) ((ptreg).gpr[27]) -#define PTREG_R28(ptreg) ((ptreg).gpr[28]) -#define PTREG_R29(ptreg) ((ptreg).gpr[29]) -#define PTREG_R30(ptreg) ((ptreg).gpr[30]) -#define PTREG_R31(ptreg) ((ptreg).gpr[31]) -#define PTREG_Nip(ptreg) ((ptreg).nip) -#define PTREG_Msr(ptreg) ((ptreg).msr) -#define PTREG_Ctr(ptreg) ((ptreg).ctr) -#define PTREG_Link(ptreg) ((ptreg).link) -#define PTREG_Xer(ptreg) ((ptreg).xer) -#define PTREG_Ccr(ptreg) ((ptreg).ccr) -#else //HOST_POWERPC64 - #define PTREG_Rbx(ptreg) ((ptreg).rbx) #define PTREG_Rcx(ptreg) ((ptreg).rcx) #define PTREG_Rdx(ptreg) ((ptreg).rdx) @@ -858,7 +776,6 @@ const VfpSigFrame* GetConstNativeSigSimdContext(const native_context_t *mc) #define PTREG_R14(ptreg) ((ptreg).r14) #define PTREG_R15(ptreg) ((ptreg).r15) -#endif //HOST_POWERPC64 #else // HOST_64BIT #if defined(HOST_ARM) @@ -964,8 +881,6 @@ inline static DWORD64 CONTEXTGetPC(LPCONTEXT pContext) return pContext->Pc; #elif defined(HOST_S390X) return pContext->PSWAddr; -#elif defined(HOST_POWERPC64) - return pContext->Nip; #else #error "don't know how to get the program counter for this architecture" #endif @@ -983,8 +898,6 @@ inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc) pContext->Pc = pc; #elif defined(HOST_S390X) pContext->PSWAddr = pc; -#elif defined(HOST_POWERPC64) - pContext->Nip = pc; #else #error "don't know how to set the program counter for this architecture" #endif @@ -1004,8 +917,6 @@ inline static DWORD64 CONTEXTGetFP(LPCONTEXT pContext) return pContext->Fp; #elif defined(HOST_S390X) return pContext->R11; -#elif defined(HOST_POWERPC64) - return pContext->R31; #else #error "don't know how to get the frame pointer for this architecture" #endif diff --git a/src/coreclr/pal/src/include/pal/virtual.h b/src/coreclr/pal/src/include/pal/virtual.h index 902e3f4fdd6f6..bac28112ba378 100644 --- a/src/coreclr/pal/src/include/pal/virtual.h +++ b/src/coreclr/pal/src/include/pal/virtual.h @@ -180,24 +180,17 @@ class ExecutableMemoryAllocator int32_t GenerateRandomStartOffset(); private: - // There does not seem to be an easy way find the size of a library on Unix. - // So this constant represents an approximation of the libcoreclr size + // So this constant represents an approximation of the libcoreclr size (on debug build) // that can be used to calculate an approximate location of the memory that // is in 2GB range from the coreclr library. In addition, having precise size of libcoreclr // is not necessary for the calculations. - static const int32_t CoreClrLibrarySize = 16 * 1024 * 1024; + static const int32_t CoreClrLibrarySize = 100 * 1024 * 1024; // This constant represent the max size of the virtual memory that this allocator // will try to reserve during initialization. We want all JIT-ed code and the - // entire libcoreclr to be located in a 2GB range on x86 -#if defined(TARGET_ARM) || defined(TARGET_ARM64) - // It seems to be more difficult to reserve a 2Gb chunk on arm so we'll try smaller one - static const int32_t MaxExecutableMemorySize = 1024 * 1024 * 1024; -#else + // entire libcoreclr to be located in a 2GB range. static const int32_t MaxExecutableMemorySize = 0x7FFF0000; -#endif - static const int32_t MaxExecutableMemorySizeNearCoreClr = MaxExecutableMemorySize - CoreClrLibrarySize; // Start address of the reserved virtual address space diff --git a/src/coreclr/pal/src/locale/utf8.cpp b/src/coreclr/pal/src/locale/utf8.cpp index c0cf19dba5d7f..8ff3229fcbaba 100644 --- a/src/coreclr/pal/src/locale/utf8.cpp +++ b/src/coreclr/pal/src/locale/utf8.cpp @@ -1075,7 +1075,7 @@ class UTF8Encoding DecoderReplacementFallback decoderReplacementFallback; DecoderExceptionFallback decoderExceptionFallback; - bool InRange(int c, int begin, int end) + bool InRange(WCHAR c, WCHAR begin, WCHAR end) { return begin <= c && c <= end; } diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index ad3a453aa539f..55b6aa3fecf0e 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -2284,13 +2284,7 @@ void * MAPMapPEFile(HANDLE hFile, off_t offset) // more efficient code (by avoiding usage of jump stubs). Alignment to a 64 KB granularity should // not be necessary (alignment to page size should be sufficient), but see // ExecutableMemoryAllocator::AllocateMemory() for the reason why it is done. - -#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION - if (!g_useDefaultBaseAddr) -#endif // FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION - { - loadedBase = ReserveMemoryFromExecutableAllocator(pThread, ALIGN_UP(reserveSize, VIRTUAL_64KB)); - } + loadedBase = ReserveMemoryFromExecutableAllocator(pThread, ALIGN_UP(reserveSize, VIRTUAL_64KB)); #endif // HOST_64BIT if (loadedBase == NULL) diff --git a/src/coreclr/pal/src/map/virtual.cpp b/src/coreclr/pal/src/map/virtual.cpp index 8f4c87e67e4bf..64ecf1ff48a84 100644 --- a/src/coreclr/pal/src/map/virtual.cpp +++ b/src/coreclr/pal/src/map/virtual.cpp @@ -2140,15 +2140,7 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory() int32_t preferredStartAddressIncrement; UINT_PTR preferredStartAddress; UINT_PTR coreclrLoadAddress; - -#if defined(TARGET_ARM) || defined(TARGET_ARM64) - // Smaller steps on ARM because we try hard finding a spare memory in a 128Mb - // distance from coreclr so e.g. all calls from corelib to coreclr could use relocs - const int32_t AddressProbingIncrement = 8 * 1024 * 1024; -#else - const int32_t AddressProbingIncrement = 128 * 1024 * 1024; -#endif - const int32_t SizeProbingDecrement = 128 * 1024 * 1024; + const int32_t MemoryProbingIncrement = 128 * 1024 * 1024; // Try to find and reserve an available region of virtual memory that is located // within 2GB range (defined by the MaxExecutableMemorySizeNearCoreClr constant) from the @@ -2169,18 +2161,12 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory() { // Try to allocate above the location of libcoreclr preferredStartAddress = coreclrLoadAddress + CoreClrLibrarySize; - preferredStartAddressIncrement = AddressProbingIncrement; + preferredStartAddressIncrement = MemoryProbingIncrement; } else { // Try to allocate below the location of libcoreclr -#if defined(TARGET_ARM) || defined(TARGET_ARM64) - // For arm for the "high address" case it only makes sense to try to reserve 128Mb - // and if it doesn't work - we'll reserve a full-sized region in a random location - sizeOfAllocation = SizeProbingDecrement; -#endif - - preferredStartAddress = coreclrLoadAddress - sizeOfAllocation; + preferredStartAddress = coreclrLoadAddress - MaxExecutableMemorySizeNearCoreClr; preferredStartAddressIncrement = 0; } @@ -2194,10 +2180,10 @@ void ExecutableMemoryAllocator::TryReserveInitialMemory() } // Try to allocate a smaller region - sizeOfAllocation -= SizeProbingDecrement; + sizeOfAllocation -= MemoryProbingIncrement; preferredStartAddress += preferredStartAddressIncrement; - } while (sizeOfAllocation >= SizeProbingDecrement); + } while (sizeOfAllocation >= MemoryProbingIncrement); if (m_startAddress == nullptr) { diff --git a/src/coreclr/pal/src/misc/cgroup.cpp b/src/coreclr/pal/src/misc/cgroup.cpp index 890ddf38363d6..955347ceda65d 100644 --- a/src/coreclr/pal/src/misc/cgroup.cpp +++ b/src/coreclr/pal/src/misc/cgroup.cpp @@ -38,10 +38,6 @@ SET_DEFAULT_DEBUG_CHANNEL(MISC); #define CGROUP1_MEMORY_LIMIT_FILENAME "/memory.limit_in_bytes" #define CGROUP2_MEMORY_LIMIT_FILENAME "/memory.max" #define CGROUP_MEMORY_STAT_FILENAME "/memory.stat" -#define CGROUP1_MEMORY_USAGE_FILENAME "/memory.usage_in_bytes" -#define CGROUP2_MEMORY_USAGE_FILENAME "/memory.current" -#define CGROUP1_MEMORY_STAT_INACTIVE_FIELD "total_inactive_file " -#define CGROUP2_MEMORY_STAT_INACTIVE_FIELD "inactive_file " #define CGROUP1_CFS_QUOTA_FILENAME "/cpu.cfs_quota_us" #define CGROUP1_CFS_PERIOD_FILENAME "/cpu.cfs_period_us" #define CGROUP2_CPU_MAX_FILENAME "/cpu.max" @@ -53,12 +49,37 @@ class CGroup static char *s_memory_cgroup_path; static char *s_cpu_cgroup_path; + + static const char *s_mem_stat_key_names[]; + static size_t s_mem_stat_key_lengths[]; + static size_t s_mem_stat_n_keys; public: static void Initialize() { s_cgroup_version = FindCGroupVersion(); s_memory_cgroup_path = FindCGroupPath(s_cgroup_version == 1 ? &IsCGroup1MemorySubsystem : nullptr); s_cpu_cgroup_path = FindCGroupPath(s_cgroup_version == 1 ? &IsCGroup1CpuSubsystem : nullptr); + + if (s_cgroup_version == 1) + { + s_mem_stat_n_keys = 4; + s_mem_stat_key_names[0] = "total_inactive_anon "; + s_mem_stat_key_names[1] = "total_active_anon "; + s_mem_stat_key_names[2] = "total_dirty "; + s_mem_stat_key_names[3] = "total_unevictable "; + } + else + { + s_mem_stat_n_keys = 3; + s_mem_stat_key_names[0] = "anon "; + s_mem_stat_key_names[1] = "file_dirty "; + s_mem_stat_key_names[2] = "unevictable "; + } + + for (size_t i = 0; i < s_mem_stat_n_keys; i++) + { + s_mem_stat_key_lengths[i] = strlen(s_mem_stat_key_names[i]); + } } static void Cleanup() @@ -87,9 +108,9 @@ class CGroup if (s_cgroup_version == 0) return false; else if (s_cgroup_version == 1) - return GetCGroupMemoryUsage(val, CGROUP1_MEMORY_USAGE_FILENAME, CGROUP1_MEMORY_STAT_INACTIVE_FIELD); + return GetCGroupMemoryUsage(val); else if (s_cgroup_version == 2) - return GetCGroupMemoryUsage(val, CGROUP2_MEMORY_USAGE_FILENAME, CGROUP2_MEMORY_STAT_INACTIVE_FIELD); + return GetCGroupMemoryUsage(val); else { _ASSERTE(!"Unknown cgroup version."); @@ -395,38 +416,8 @@ class CGroup return result; } - static bool GetCGroupMemoryUsage(size_t *val, const char *filename, const char *inactiveFileFieldName) + static bool GetCGroupMemoryUsage(size_t *val) { - // Use the same way to calculate memory load as popular container tools (Docker, Kubernetes, Containerd etc.) - // For cgroup v1: value of 'memory.usage_in_bytes' minus 'total_inactive_file' value of 'memory.stat' - // For cgroup v2: value of 'memory.current' minus 'inactive_file' value of 'memory.stat' - - char* mem_usage_filename = nullptr; - if (asprintf(&mem_usage_filename, "%s%s", s_memory_cgroup_path, filename) < 0) - return false; - - uint64_t temp = 0; - - size_t usage = 0; - - bool result = ReadMemoryValueFromFile(mem_usage_filename, &temp); - if (result) - { - if (temp > std::numeric_limits::max()) - { - usage = std::numeric_limits::max(); - } - else - { - usage = (size_t)temp; - } - } - - free(mem_usage_filename); - - if (!result) - return result; - if (s_memory_cgroup_path == nullptr) return false; @@ -441,32 +432,34 @@ class CGroup char *line = nullptr; size_t lineLen = 0; - bool foundInactiveFileValue = false; + size_t readValues = 0; char* endptr; - size_t inactiveFileFieldNameLength = strlen(inactiveFileFieldName); - - while (getline(&line, &lineLen, stat_file) != -1) + *val = 0; + while (getline(&line, &lineLen, stat_file) != -1 && readValues < s_mem_stat_n_keys) { - if (strncmp(line, inactiveFileFieldName, inactiveFileFieldNameLength) == 0) + for (size_t i = 0; i < s_mem_stat_n_keys; i++) { - errno = 0; - const char* startptr = line + inactiveFileFieldNameLength; - size_t inactiveFileValue = strtoll(startptr, &endptr, 10); - if (endptr != startptr && errno == 0) + if (strncmp(line, s_mem_stat_key_names[i], s_mem_stat_key_lengths[i]) == 0) { - foundInactiveFileValue = true; - *val = usage - inactiveFileValue; - } + errno = 0; + const char* startptr = line + s_mem_stat_key_lengths[i]; + *val += strtoll(startptr, &endptr, 10); + if (endptr != startptr && errno == 0) + readValues++; - break; + break; + } } } fclose(stat_file); free(line); - return foundInactiveFileValue; + if (readValues == s_mem_stat_n_keys) + return true; + + return false; } static bool ReadMemoryValueFromFile(const char* filename, uint64_t* val) @@ -631,6 +624,10 @@ int CGroup::s_cgroup_version = 0; char *CGroup::s_memory_cgroup_path = nullptr; char *CGroup::s_cpu_cgroup_path = nullptr; +const char *CGroup::s_mem_stat_key_names[4] = {}; +size_t CGroup::s_mem_stat_key_lengths[4] = {}; +size_t CGroup::s_mem_stat_n_keys = 0; + void InitializeCGroup() { CGroup::Initialize(); diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index df7e97af53087..f0c980a61efab 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -50,8 +50,6 @@ namespace ELF_MACHINE = EM_LOONGARCH, #elif defined(HOST_S390X) ELF_MACHINE = EM_S390, -#elif defined(HOST_POWERPC) - ELF_MACHINE = EM_PPC64, #else #error ELF_MACHINE unsupported for target #endif diff --git a/src/coreclr/pal/src/misc/sysinfo.cpp b/src/coreclr/pal/src/misc/sysinfo.cpp index b8840eff00219..eb679d3d24957 100644 --- a/src/coreclr/pal/src/misc/sysinfo.cpp +++ b/src/coreclr/pal/src/misc/sysinfo.cpp @@ -539,31 +539,23 @@ ReadMemoryValueFromFile(const char* filename, uint64_t* val) return result; } -#define UPDATE_CACHE_SIZE_AND_LEVEL(CACHE_LEVEL) if (size > cacheSize) { cacheSize = size; cacheLevel = CACHE_LEVEL; } - size_t PALAPI PAL_GetLogicalProcessorCacheSizeFromOS() { - size_t cacheLevel = 0; size_t cacheSize = 0; - size_t size; #ifdef _SC_LEVEL1_DCACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL1_DCACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(1) + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL1_DCACHE_SIZE)); #endif #ifdef _SC_LEVEL2_CACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL2_CACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(2) + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL2_CACHE_SIZE)); #endif #ifdef _SC_LEVEL3_CACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL3_CACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(3) + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL3_CACHE_SIZE)); #endif #ifdef _SC_LEVEL4_CACHE_SIZE - size = ( size_t) sysconf(_SC_LEVEL4_CACHE_SIZE); - UPDATE_CACHE_SIZE_AND_LEVEL(4) + cacheSize = std::max(cacheSize, (size_t)sysconf(_SC_LEVEL4_CACHE_SIZE)); #endif #if defined(TARGET_LINUX) && !defined(HOST_ARM) && !defined(HOST_X86) @@ -574,39 +566,25 @@ PAL_GetLogicalProcessorCacheSizeFromOS() // for the platform. Currently musl and arm64 should be only cases to use // this method to determine cache size. // - size_t level; - char path_to_size_file[] = "/sys/devices/system/cpu/cpu0/cache/index-/size"; - char path_to_level_file[] = "/sys/devices/system/cpu/cpu0/cache/index-/level"; - int index = 40; - _ASSERTE(path_to_size_file[index] == '-'); - _ASSERTE(path_to_level_file[index] == '-'); - - for (int i = 0; i < 5; i++) - { - path_to_size_file[index] = (char)(48 + i); - - if (ReadMemoryValueFromFile(path_to_size_file, &size)) - { - path_to_level_file[index] = (char)(48 + i); - - if (ReadMemoryValueFromFile(path_to_level_file, &level)) - { - UPDATE_CACHE_SIZE_AND_LEVEL(level) - } - else - { - cacheSize = std::max(cacheSize, size); - } - } - } + size_t size; + + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index0/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index1/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index2/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index3/size", &size)) + cacheSize = std::max(cacheSize, size); + if(ReadMemoryValueFromFile("/sys/devices/system/cpu/cpu0/cache/index4/size", &size)) + cacheSize = std::max(cacheSize, size); } #endif #if (defined(HOST_ARM64) || defined(HOST_LOONGARCH64)) && !defined(TARGET_OSX) if (cacheSize == 0) { - // We expect to get the L3 cache size for Arm64 but currently expected to be missing that info - // from most of the machines with an exceptions on some machines. + // It is currently expected to be missing cache size info // // _SC_LEVEL*_*CACHE_SIZE is not yet present. Work is in progress to enable this for arm64 // @@ -643,43 +621,12 @@ PAL_GetLogicalProcessorCacheSizeFromOS() || sysctlbyname("hw.l3cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.l2cachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0 || sysctlbyname("hw.l1dcachesize", &cacheSizeFromSysctl, &sz, nullptr, 0) == 0; + if (success) { _ASSERTE(cacheSizeFromSysctl > 0); - cacheSize = ( size_t) cacheSizeFromSysctl; - } - } -#endif - -#if (defined(HOST_ARM64) || defined(HOST_LOONGARCH64)) && !defined(TARGET_OSX) - if (cacheLevel != 3) - { - // We expect to get the L3 cache size for Arm64 but currently expected to be missing that info - // from most of the machines. - // Hence, just use the following heuristics at best depending on the CPU count - // 1 ~ 4 : 4 MB - // 5 ~ 16 : 8 MB - // 17 ~ 64 : 16 MB - // 65+ : 32 MB - DWORD logicalCPUs = PAL_GetLogicalCpuCountFromOS(); - if (logicalCPUs < 5) - { - cacheSize = 4; - } - else if (logicalCPUs < 17) - { - cacheSize = 8; + cacheSize = (size_t) cacheSizeFromSysctl; } - else if (logicalCPUs < 65) - { - cacheSize = 16; - } - else - { - cacheSize = 32; - } - - cacheSize *= (1024 * 1024); } #endif diff --git a/src/coreclr/pal/src/misc/time.cpp b/src/coreclr/pal/src/misc/time.cpp index 7d78ae930c397..ec71e5c72b06c 100644 --- a/src/coreclr/pal/src/misc/time.cpp +++ b/src/coreclr/pal/src/misc/time.cpp @@ -82,13 +82,13 @@ GetSystemTime( goto EXIT; } - lpSystemTime->wYear = (WORD)(1900 + utPtr->tm_year); - lpSystemTime->wMonth = (WORD)(utPtr->tm_mon + 1); - lpSystemTime->wDayOfWeek = (WORD)utPtr->tm_wday; - lpSystemTime->wDay = (WORD)utPtr->tm_mday; - lpSystemTime->wHour = (WORD)utPtr->tm_hour; - lpSystemTime->wMinute = (WORD)utPtr->tm_min; - lpSystemTime->wSecond = (WORD)utPtr->tm_sec; + lpSystemTime->wYear = 1900 + utPtr->tm_year; + lpSystemTime->wMonth = utPtr->tm_mon + 1; + lpSystemTime->wDayOfWeek = utPtr->tm_wday; + lpSystemTime->wDay = utPtr->tm_mday; + lpSystemTime->wHour = utPtr->tm_hour; + lpSystemTime->wMinute = utPtr->tm_min; + lpSystemTime->wSecond = utPtr->tm_sec; if(-1 == timeofday_retval) { @@ -101,7 +101,7 @@ GetSystemTime( int old_seconds; int new_seconds; - lpSystemTime->wMilliseconds = (WORD)(timeval.tv_usec/tccMillieSecondsToMicroSeconds); + lpSystemTime->wMilliseconds = timeval.tv_usec/tccMillieSecondsToMicroSeconds; old_seconds = utPtr->tm_sec; new_seconds = timeval.tv_sec%60; diff --git a/src/coreclr/pal/src/safecrt/input.inl b/src/coreclr/pal/src/safecrt/input.inl index e68dc42f01614..3f415d695833a 100644 --- a/src/coreclr/pal/src/safecrt/input.inl +++ b/src/coreclr/pal/src/safecrt/input.inl @@ -665,7 +665,7 @@ scanit: } else #else /* _UNICODE */ if (fl_wchar_arg) { - *(char16_t UNALIGNED *)pointer = (char16_t)ch; + *(char16_t UNALIGNED *)pointer = ch; pointer = (char16_t *)pointer + 1; #ifdef _SECURE_SCANF --array_width; @@ -867,7 +867,7 @@ getnum: if (_ISXDIGIT(ch)) { num64 <<= 4; - ch = _hextodec((_TCHAR)ch); + ch = _hextodec(ch); } else ++done_flag; @@ -910,7 +910,7 @@ getnum: if (_ISXDIGIT(ch)) { number = (number << 4); - ch = _hextodec((_TCHAR)ch); + ch = _hextodec(ch); } else ++done_flag; @@ -1262,7 +1262,7 @@ static int __cdecl _inc(miniFILE* fileptr) static void __cdecl _un_inc(int chr, miniFILE* fileptr) { if (_TEOF != chr) { - _ungettc_nolock((char)chr,fileptr); + _ungettc_nolock(chr,fileptr); } } diff --git a/src/coreclr/pal/src/safecrt/wcslwr_s.cpp b/src/coreclr/pal/src/safecrt/wcslwr_s.cpp index 184776f21ee95..f80ff7bcf344a 100644 --- a/src/coreclr/pal/src/safecrt/wcslwr_s.cpp +++ b/src/coreclr/pal/src/safecrt/wcslwr_s.cpp @@ -30,7 +30,7 @@ DLLEXPORT errno_t __cdecl _wcslwr_s(char16_t *string, size_t sz) for (int i = 0; string[i] != 0; i++) { - string[i] = (char16_t)towlower(string[i]); + string[i] = towlower(string[i]); } _FILL_STRING(string, sz, length + 1); diff --git a/src/coreclr/pal/src/thread/context.cpp b/src/coreclr/pal/src/thread/context.cpp index 92d2ef085f3e9..5c9f89d03b201 100644 --- a/src/coreclr/pal/src/thread/context.cpp +++ b/src/coreclr/pal/src/thread/context.cpp @@ -45,8 +45,6 @@ extern PGET_GCMARKER_EXCEPTION_CODE g_getGcMarkerExceptionCode; #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #elif defined(HOST_S390X) #define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT -#elif defined(HOST_POWERPC64) -#define CONTEXT_ALL_FLOATING CONTEXT_FLOATING_POINT #else #error Unexpected architecture. #endif @@ -234,50 +232,6 @@ typedef int __ptrace_request; ASSIGN_REG(R13) \ ASSIGN_REG(R14) -#elif defined(HOST_POWERPC64) -#define ASSIGN_CONTROL_REGS \ - ASSIGN_REG(Nip) \ - ASSIGN_REG(Msr) \ - ASSIGN_REG(Ctr) \ - ASSIGN_REG(Link) \ - ASSIGN_REG(Xer) \ - ASSIGN_REG(Ccr) \ - ASSIGN_REG(R31) \ - -#define ASSIGN_INTEGER_REGS \ - ASSIGN_REG(R0) \ - ASSIGN_REG(R1) \ - ASSIGN_REG(R2) \ - ASSIGN_REG(R3) \ - ASSIGN_REG(R4) \ - ASSIGN_REG(R5) \ - ASSIGN_REG(R5) \ - ASSIGN_REG(R6) \ - ASSIGN_REG(R7) \ - ASSIGN_REG(R8) \ - ASSIGN_REG(R9) \ - ASSIGN_REG(R10) \ - ASSIGN_REG(R11) \ - ASSIGN_REG(R12) \ - ASSIGN_REG(R13) \ - ASSIGN_REG(R14) \ - ASSIGN_REG(R15) \ - ASSIGN_REG(R16) \ - ASSIGN_REG(R17) \ - ASSIGN_REG(R18) \ - ASSIGN_REG(R19) \ - ASSIGN_REG(R20) \ - ASSIGN_REG(R21) \ - ASSIGN_REG(R22) \ - ASSIGN_REG(R23) \ - ASSIGN_REG(R24) \ - ASSIGN_REG(R25) \ - ASSIGN_REG(R26) \ - ASSIGN_REG(R27) \ - ASSIGN_REG(R28) \ - ASSIGN_REG(R29) \ - ASSIGN_REG(R30) - #else #error "Don't know how to assign registers on this architecture" #endif @@ -545,7 +499,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) #undef ASSIGN_REG #if !HAVE_FPREGS_WITH_CW -#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) && !defined(HOST_POWERPC64) +#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) #if HAVE_GREGSET_T if (native->uc_mcontext.fpregs == nullptr) #elif HAVE___GREGSET_T @@ -557,7 +511,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native) // whether CONTEXT_FLOATING_POINT is set in the CONTEXT's flags. return; } -#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X && !HOST_LOONGARCH64 && !HOST_POWERPC64 +#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X && !HOST_LOONGARCH64 #endif // !HAVE_FPREGS_WITH_CW if ((lpContext->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) @@ -680,7 +634,7 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex #undef ASSIGN_REG #if !HAVE_FPREGS_WITH_CW -#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) && !defined(HOST_POWERPC64) +#if (HAVE_GREGSET_T || HAVE___GREGSET_T) && !defined(HOST_S390X) && !defined(HOST_LOONGARCH64) #if HAVE_GREGSET_T if (native->uc_mcontext.fpregs == nullptr) #elif HAVE___GREGSET_T @@ -702,7 +656,7 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex // Bail out regardless of whether the caller wanted CONTEXT_FLOATING_POINT or CONTEXT_XSTATE return; } -#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X && !HOST_POWERPC64 +#endif // (HAVE_GREGSET_T || HAVE___GREGSET_T) && !HOST_S390X #endif // !HAVE_FPREGS_WITH_CW if ((contextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) @@ -831,8 +785,6 @@ LPVOID GetNativeContextPC(const native_context_t *context) return (LPVOID) MCREG_Pc(context->uc_mcontext); #elif defined(HOST_S390X) return (LPVOID) MCREG_PSWAddr(context->uc_mcontext); -#elif defined(HOST_POWERPC64) - return (LPVOID) MCREG_Nip(context->uc_mcontext); #else # error implement me for this architecture #endif @@ -865,8 +817,6 @@ LPVOID GetNativeContextSP(const native_context_t *context) return (LPVOID) MCREG_Sp(context->uc_mcontext); #elif defined(HOST_S390X) return (LPVOID) MCREG_R15(context->uc_mcontext); -#elif defined(HOST_POWERPC64) - return (LPVOID) MCREG_R31(context->uc_mcontext); #else # error implement me for this architecture #endif diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index c36ac0e3c8bc6..bf3be74203bbf 100644 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -323,13 +323,11 @@ def add_core_root_arguments(parser, build_type_default, build_type_help): replay_parser.add_argument("-jit_path", help="Path to clrjit. Defaults to Core_Root JIT.") replay_parser.add_argument("-jitoption", action="append", help="Pass option through to the jit. Format is key=value, where key is the option name without leading COMPlus_") -# common subparser for asmdiffs and throughput base_diff_parser = argparse.ArgumentParser(add_help=False) base_diff_parser.add_argument("-base_jit_path", help="Path to baseline clrjit. Defaults to baseline JIT from rolling build, by computing baseline git hash.") base_diff_parser.add_argument("-diff_jit_path", help="Path to diff clrjit. Defaults to Core_Root JIT.") base_diff_parser.add_argument("-git_hash", help="Use this git hash as the current hash for use to find a baseline JIT. Defaults to current git hash of source tree.") base_diff_parser.add_argument("-base_git_hash", help="Use this git hash as the baseline JIT hash. Default: search for the baseline hash.") -base_diff_parser.add_argument("-jitoption", action="append", help="Option to pass to both baseline and diff JIT. Format is key=value, where key is the option name without leading COMPlus_") base_diff_parser.add_argument("-base_jit_option", action="append", help="Option to pass to the baseline JIT. Format is key=value, where key is the option name without leading COMPlus_...") base_diff_parser.add_argument("-diff_jit_option", action="append", help="Option to pass to the diff JIT. Format is key=value, where key is the option name without leading COMPlus_...") @@ -1467,9 +1465,6 @@ def replay_with_asm_diffs(self): if self.coreclr_args.base_jit_option: for o in self.coreclr_args.base_jit_option: base_option_flags += "-jitoption", o - if self.coreclr_args.jitoption: - for o in self.coreclr_args.jitoption: - base_option_flags += "-jitoption", o base_option_flags_for_diff_artifact = base_option_flags diff_option_flags = [] @@ -1478,10 +1473,6 @@ def replay_with_asm_diffs(self): for o in self.coreclr_args.diff_jit_option: diff_option_flags += "-jit2option", o diff_option_flags_for_diff_artifact += "-jitoption", o - if self.coreclr_args.jitoption: - for o in self.coreclr_args.jitoption: - diff_option_flags += "-jit2option", o - diff_option_flags_for_diff_artifact += "-jitoption", o if self.coreclr_args.altjit: altjit_asm_diffs_flags += [ @@ -3385,11 +3376,6 @@ def verify_base_diff_args(): lambda unused: True, "Unable to set base_git_hash") - coreclr_args.verify(args, - "jitoption", - lambda unused: True, - "Unable to set jitoption") - coreclr_args.verify(args, "base_jit_option", lambda unused: True, diff --git a/src/coreclr/scripts/superpmi_aspnet.py b/src/coreclr/scripts/superpmi_aspnet.py index 03f8757a702c9..e2aeecf2a478d 100644 --- a/src/coreclr/scripts/superpmi_aspnet.py +++ b/src/coreclr/scripts/superpmi_aspnet.py @@ -132,8 +132,8 @@ def build_and_run(coreclr_args): print ("Executing in " + temp_location) - # install dotnet 6.0 - run_command([dotnet_install_script_path, "-Version", "6.0.4"], temp_location, _exit_on_fail=True) + # install dotnet 5.0 + run_command([dotnet_install_script_path, "-Version", "5.0.3"], temp_location, _exit_on_fail=True) os.environ['DOTNET_MULTILEVEL_LOOKUP'] = '0' os.environ['DOTNET_SKIP_FIRST_TIME_EXPERIENCE'] = '1' dotnet_path = path.join(source_directory, ".dotnet") diff --git a/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs b/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs index 549d8fbd290b2..0c4b0e1684473 100644 --- a/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs +++ b/src/coreclr/tools/Common/Compiler/DisplayNameHelpers.cs @@ -12,7 +12,7 @@ namespace ILCompiler { - public static class DisplayNameHelpers + internal static class DisplayNameHelpers { public static string GetDisplayName(this TypeSystemEntity entity) { diff --git a/src/coreclr/tools/Common/Internal/Runtime/EETypeBuilderHelpers.cs b/src/coreclr/tools/Common/Internal/Runtime/EETypeBuilderHelpers.cs index a225665dcee12..dd34d85aaa569 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/EETypeBuilderHelpers.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/EETypeBuilderHelpers.cs @@ -121,7 +121,7 @@ internal static uint ComputeValueTypeFieldPaddingFieldValue(uint padding, uint a while ((alignment & 1) == 0) { alignmentLog2++; - alignment >>= 1; + alignment = alignment >> 1; } Debug.Assert(alignment == 1); diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index d9671ef058ae1..30d8af4efb23c 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -15,7 +15,7 @@ internal struct ReadyToRunHeaderConstants public const uint Signature = 0x00525452; // 'RTR' public const ushort CurrentMajorVersion = 6; - public const ushort CurrentMinorVersion = 2; + public const ushort CurrentMinorVersion = 1; } #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index c618b88859585..fa7a9f8688d50 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -100,20 +100,6 @@ static CorInfoInline _canInline(IntPtr thisHandle, IntPtr* ppException, CORINFO_ } } - [UnmanagedCallersOnly] - static void _beginInlining(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* inlinerHnd, CORINFO_METHOD_STRUCT_* inlineeHnd) - { - var _this = GetThis(thisHandle); - try - { - _this.beginInlining(inlinerHnd, inlineeHnd); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - } - } - [UnmanagedCallersOnly] static void _reportInliningDecision(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* inlinerHnd, CORINFO_METHOD_STRUCT_* inlineeHnd, CorInfoInline inlineResult, byte* reason) { @@ -2566,7 +2552,7 @@ static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_FLAGS* f static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 173); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 172); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2574,173 +2560,172 @@ static IntPtr GetUnmanagedCallbacks() callbacks[3] = (delegate* unmanaged)&_getMethodSig; callbacks[4] = (delegate* unmanaged)&_getMethodInfo; callbacks[5] = (delegate* unmanaged)&_canInline; - callbacks[6] = (delegate* unmanaged)&_beginInlining; - callbacks[7] = (delegate* unmanaged)&_reportInliningDecision; - callbacks[8] = (delegate* unmanaged)&_canTailCall; - callbacks[9] = (delegate* unmanaged)&_reportTailCallDecision; - callbacks[10] = (delegate* unmanaged)&_getEHinfo; - callbacks[11] = (delegate* unmanaged)&_getMethodClass; - callbacks[12] = (delegate* unmanaged)&_getMethodModule; - callbacks[13] = (delegate* unmanaged)&_getMethodVTableOffset; - callbacks[14] = (delegate* unmanaged)&_resolveVirtualMethod; - callbacks[15] = (delegate* unmanaged)&_getUnboxedEntry; - callbacks[16] = (delegate* unmanaged)&_getDefaultComparerClass; - callbacks[17] = (delegate* unmanaged)&_getDefaultEqualityComparerClass; - callbacks[18] = (delegate* unmanaged)&_expandRawHandleIntrinsic; - callbacks[19] = (delegate* unmanaged)&_isIntrinsicType; - callbacks[20] = (delegate* unmanaged)&_getUnmanagedCallConv; - callbacks[21] = (delegate* unmanaged)&_pInvokeMarshalingRequired; - callbacks[22] = (delegate* unmanaged)&_satisfiesMethodConstraints; - callbacks[23] = (delegate* unmanaged)&_isCompatibleDelegate; - callbacks[24] = (delegate* unmanaged)&_methodMustBeLoadedBeforeCodeIsRun; - callbacks[25] = (delegate* unmanaged)&_mapMethodDeclToMethodImpl; - callbacks[26] = (delegate* unmanaged)&_getGSCookie; - callbacks[27] = (delegate* unmanaged)&_setPatchpointInfo; - callbacks[28] = (delegate* unmanaged)&_getOSRInfo; - callbacks[29] = (delegate* unmanaged)&_resolveToken; - callbacks[30] = (delegate* unmanaged)&_tryResolveToken; - callbacks[31] = (delegate* unmanaged)&_findSig; - callbacks[32] = (delegate* unmanaged)&_findCallSiteSig; - callbacks[33] = (delegate* unmanaged)&_getTokenTypeAsHandle; - callbacks[34] = (delegate* unmanaged)&_isValidToken; - callbacks[35] = (delegate* unmanaged)&_isValidStringRef; - callbacks[36] = (delegate* unmanaged)&_getStringLiteral; - callbacks[37] = (delegate* unmanaged)&_asCorInfoType; - callbacks[38] = (delegate* unmanaged)&_getClassName; - callbacks[39] = (delegate* unmanaged)&_getClassNameFromMetadata; - callbacks[40] = (delegate* unmanaged)&_getTypeInstantiationArgument; - callbacks[41] = (delegate* unmanaged)&_appendClassName; - callbacks[42] = (delegate* unmanaged)&_isValueClass; - callbacks[43] = (delegate* unmanaged)&_canInlineTypeCheck; - callbacks[44] = (delegate* unmanaged)&_getClassAttribs; - callbacks[45] = (delegate* unmanaged)&_getClassModule; - callbacks[46] = (delegate* unmanaged)&_getModuleAssembly; - callbacks[47] = (delegate* unmanaged)&_getAssemblyName; - callbacks[48] = (delegate* unmanaged)&_LongLifetimeMalloc; - callbacks[49] = (delegate* unmanaged)&_LongLifetimeFree; - callbacks[50] = (delegate* unmanaged)&_getClassModuleIdForStatics; - callbacks[51] = (delegate* unmanaged)&_getClassSize; - callbacks[52] = (delegate* unmanaged)&_getHeapClassSize; - callbacks[53] = (delegate* unmanaged)&_canAllocateOnStack; - callbacks[54] = (delegate* unmanaged)&_getClassAlignmentRequirement; - callbacks[55] = (delegate* unmanaged)&_getClassGClayout; - callbacks[56] = (delegate* unmanaged)&_getClassNumInstanceFields; - callbacks[57] = (delegate* unmanaged)&_getFieldInClass; - callbacks[58] = (delegate* unmanaged)&_checkMethodModifier; - callbacks[59] = (delegate* unmanaged)&_getNewHelper; - callbacks[60] = (delegate* unmanaged)&_getNewArrHelper; - callbacks[61] = (delegate* unmanaged)&_getCastingHelper; - callbacks[62] = (delegate* unmanaged)&_getSharedCCtorHelper; - callbacks[63] = (delegate* unmanaged)&_getTypeForBox; - callbacks[64] = (delegate* unmanaged)&_getBoxHelper; - callbacks[65] = (delegate* unmanaged)&_getUnBoxHelper; - callbacks[66] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[67] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; - callbacks[68] = (delegate* unmanaged)&_getHelperName; - callbacks[69] = (delegate* unmanaged)&_initClass; - callbacks[70] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; - callbacks[71] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[72] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[73] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[74] = (delegate* unmanaged)&_canCast; - callbacks[75] = (delegate* unmanaged)&_areTypesEquivalent; - callbacks[76] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[77] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[78] = (delegate* unmanaged)&_mergeClasses; - callbacks[79] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[80] = (delegate* unmanaged)&_getParentType; - callbacks[81] = (delegate* unmanaged)&_getChildType; - callbacks[82] = (delegate* unmanaged)&_satisfiesClassConstraints; - callbacks[83] = (delegate* unmanaged)&_isSDArray; - callbacks[84] = (delegate* unmanaged)&_getArrayRank; - callbacks[85] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[86] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[87] = (delegate* unmanaged)&_canAccessClass; - callbacks[88] = (delegate* unmanaged)&_getFieldName; - callbacks[89] = (delegate* unmanaged)&_getFieldClass; - callbacks[90] = (delegate* unmanaged)&_getFieldType; - callbacks[91] = (delegate* unmanaged)&_getFieldOffset; - callbacks[92] = (delegate* unmanaged)&_getFieldInfo; - callbacks[93] = (delegate* unmanaged)&_isFieldStatic; - callbacks[94] = (delegate* unmanaged)&_getBoundaries; - callbacks[95] = (delegate* unmanaged)&_setBoundaries; - callbacks[96] = (delegate* unmanaged)&_getVars; - callbacks[97] = (delegate* unmanaged)&_setVars; - callbacks[98] = (delegate* unmanaged)&_allocateArray; - callbacks[99] = (delegate* unmanaged)&_freeArray; - callbacks[100] = (delegate* unmanaged)&_getArgNext; - callbacks[101] = (delegate* unmanaged)&_getArgType; - callbacks[102] = (delegate* unmanaged)&_getArgClass; - callbacks[103] = (delegate* unmanaged)&_getHFAType; - callbacks[104] = (delegate* unmanaged)&_GetErrorHRESULT; - callbacks[105] = (delegate* unmanaged)&_GetErrorMessage; - callbacks[106] = (delegate* unmanaged)&_FilterException; - callbacks[107] = (delegate* unmanaged)&_ThrowExceptionForJitResult; - callbacks[108] = (delegate* unmanaged)&_ThrowExceptionForHelper; - callbacks[109] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[110] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[111] = (delegate* unmanaged)&_getEEInfo; - callbacks[112] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[113] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[114] = (delegate* unmanaged)&_getMethodName; - callbacks[115] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[116] = (delegate* unmanaged)&_getMethodHash; - callbacks[117] = (delegate* unmanaged)&_findNameOfToken; - callbacks[118] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[119] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[120] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[121] = (delegate* unmanaged)&_getInlinedCallFrameVptr; - callbacks[122] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[123] = (delegate* unmanaged)&_getHelperFtn; - callbacks[124] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[125] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[126] = (delegate* unmanaged)&_getMethodSync; - callbacks[127] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[128] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[129] = (delegate* unmanaged)&_embedClassHandle; - callbacks[130] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[131] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[132] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[133] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[134] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[135] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[136] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[137] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[138] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[139] = (delegate* unmanaged)&_getCallInfo; - callbacks[140] = (delegate* unmanaged)&_canAccessFamily; - callbacks[141] = (delegate* unmanaged)&_isRIDClassDomainID; - callbacks[142] = (delegate* unmanaged)&_getClassDomainID; - callbacks[143] = (delegate* unmanaged)&_getFieldAddress; - callbacks[144] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[145] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[146] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[147] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[148] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[149] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[150] = (delegate* unmanaged)&_addActiveDependency; - callbacks[151] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[152] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[153] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[154] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[155] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[156] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[157] = (delegate* unmanaged)&_allocMem; - callbacks[158] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[159] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[160] = (delegate* unmanaged)&_allocGCInfo; - callbacks[161] = (delegate* unmanaged)&_setEHcount; - callbacks[162] = (delegate* unmanaged)&_setEHinfo; - callbacks[163] = (delegate* unmanaged)&_logMsg; - callbacks[164] = (delegate* unmanaged)&_doAssert; - callbacks[165] = (delegate* unmanaged)&_reportFatalError; - callbacks[166] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[167] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[168] = (delegate* unmanaged)&_recordCallSite; - callbacks[169] = (delegate* unmanaged)&_recordRelocation; - callbacks[170] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[171] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[172] = (delegate* unmanaged)&_getJitFlags; + callbacks[6] = (delegate* unmanaged)&_reportInliningDecision; + callbacks[7] = (delegate* unmanaged)&_canTailCall; + callbacks[8] = (delegate* unmanaged)&_reportTailCallDecision; + callbacks[9] = (delegate* unmanaged)&_getEHinfo; + callbacks[10] = (delegate* unmanaged)&_getMethodClass; + callbacks[11] = (delegate* unmanaged)&_getMethodModule; + callbacks[12] = (delegate* unmanaged)&_getMethodVTableOffset; + callbacks[13] = (delegate* unmanaged)&_resolveVirtualMethod; + callbacks[14] = (delegate* unmanaged)&_getUnboxedEntry; + callbacks[15] = (delegate* unmanaged)&_getDefaultComparerClass; + callbacks[16] = (delegate* unmanaged)&_getDefaultEqualityComparerClass; + callbacks[17] = (delegate* unmanaged)&_expandRawHandleIntrinsic; + callbacks[18] = (delegate* unmanaged)&_isIntrinsicType; + callbacks[19] = (delegate* unmanaged)&_getUnmanagedCallConv; + callbacks[20] = (delegate* unmanaged)&_pInvokeMarshalingRequired; + callbacks[21] = (delegate* unmanaged)&_satisfiesMethodConstraints; + callbacks[22] = (delegate* unmanaged)&_isCompatibleDelegate; + callbacks[23] = (delegate* unmanaged)&_methodMustBeLoadedBeforeCodeIsRun; + callbacks[24] = (delegate* unmanaged)&_mapMethodDeclToMethodImpl; + callbacks[25] = (delegate* unmanaged)&_getGSCookie; + callbacks[26] = (delegate* unmanaged)&_setPatchpointInfo; + callbacks[27] = (delegate* unmanaged)&_getOSRInfo; + callbacks[28] = (delegate* unmanaged)&_resolveToken; + callbacks[29] = (delegate* unmanaged)&_tryResolveToken; + callbacks[30] = (delegate* unmanaged)&_findSig; + callbacks[31] = (delegate* unmanaged)&_findCallSiteSig; + callbacks[32] = (delegate* unmanaged)&_getTokenTypeAsHandle; + callbacks[33] = (delegate* unmanaged)&_isValidToken; + callbacks[34] = (delegate* unmanaged)&_isValidStringRef; + callbacks[35] = (delegate* unmanaged)&_getStringLiteral; + callbacks[36] = (delegate* unmanaged)&_asCorInfoType; + callbacks[37] = (delegate* unmanaged)&_getClassName; + callbacks[38] = (delegate* unmanaged)&_getClassNameFromMetadata; + callbacks[39] = (delegate* unmanaged)&_getTypeInstantiationArgument; + callbacks[40] = (delegate* unmanaged)&_appendClassName; + callbacks[41] = (delegate* unmanaged)&_isValueClass; + callbacks[42] = (delegate* unmanaged)&_canInlineTypeCheck; + callbacks[43] = (delegate* unmanaged)&_getClassAttribs; + callbacks[44] = (delegate* unmanaged)&_getClassModule; + callbacks[45] = (delegate* unmanaged)&_getModuleAssembly; + callbacks[46] = (delegate* unmanaged)&_getAssemblyName; + callbacks[47] = (delegate* unmanaged)&_LongLifetimeMalloc; + callbacks[48] = (delegate* unmanaged)&_LongLifetimeFree; + callbacks[49] = (delegate* unmanaged)&_getClassModuleIdForStatics; + callbacks[50] = (delegate* unmanaged)&_getClassSize; + callbacks[51] = (delegate* unmanaged)&_getHeapClassSize; + callbacks[52] = (delegate* unmanaged)&_canAllocateOnStack; + callbacks[53] = (delegate* unmanaged)&_getClassAlignmentRequirement; + callbacks[54] = (delegate* unmanaged)&_getClassGClayout; + callbacks[55] = (delegate* unmanaged)&_getClassNumInstanceFields; + callbacks[56] = (delegate* unmanaged)&_getFieldInClass; + callbacks[57] = (delegate* unmanaged)&_checkMethodModifier; + callbacks[58] = (delegate* unmanaged)&_getNewHelper; + callbacks[59] = (delegate* unmanaged)&_getNewArrHelper; + callbacks[60] = (delegate* unmanaged)&_getCastingHelper; + callbacks[61] = (delegate* unmanaged)&_getSharedCCtorHelper; + callbacks[62] = (delegate* unmanaged)&_getTypeForBox; + callbacks[63] = (delegate* unmanaged)&_getBoxHelper; + callbacks[64] = (delegate* unmanaged)&_getUnBoxHelper; + callbacks[65] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[66] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[67] = (delegate* unmanaged)&_getHelperName; + callbacks[68] = (delegate* unmanaged)&_initClass; + callbacks[69] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; + callbacks[70] = (delegate* unmanaged)&_getBuiltinClass; + callbacks[71] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[72] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[73] = (delegate* unmanaged)&_canCast; + callbacks[74] = (delegate* unmanaged)&_areTypesEquivalent; + callbacks[75] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[76] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[77] = (delegate* unmanaged)&_mergeClasses; + callbacks[78] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[79] = (delegate* unmanaged)&_getParentType; + callbacks[80] = (delegate* unmanaged)&_getChildType; + callbacks[81] = (delegate* unmanaged)&_satisfiesClassConstraints; + callbacks[82] = (delegate* unmanaged)&_isSDArray; + callbacks[83] = (delegate* unmanaged)&_getArrayRank; + callbacks[84] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[85] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[86] = (delegate* unmanaged)&_canAccessClass; + callbacks[87] = (delegate* unmanaged)&_getFieldName; + callbacks[88] = (delegate* unmanaged)&_getFieldClass; + callbacks[89] = (delegate* unmanaged)&_getFieldType; + callbacks[90] = (delegate* unmanaged)&_getFieldOffset; + callbacks[91] = (delegate* unmanaged)&_getFieldInfo; + callbacks[92] = (delegate* unmanaged)&_isFieldStatic; + callbacks[93] = (delegate* unmanaged)&_getBoundaries; + callbacks[94] = (delegate* unmanaged)&_setBoundaries; + callbacks[95] = (delegate* unmanaged)&_getVars; + callbacks[96] = (delegate* unmanaged)&_setVars; + callbacks[97] = (delegate* unmanaged)&_allocateArray; + callbacks[98] = (delegate* unmanaged)&_freeArray; + callbacks[99] = (delegate* unmanaged)&_getArgNext; + callbacks[100] = (delegate* unmanaged)&_getArgType; + callbacks[101] = (delegate* unmanaged)&_getArgClass; + callbacks[102] = (delegate* unmanaged)&_getHFAType; + callbacks[103] = (delegate* unmanaged)&_GetErrorHRESULT; + callbacks[104] = (delegate* unmanaged)&_GetErrorMessage; + callbacks[105] = (delegate* unmanaged)&_FilterException; + callbacks[106] = (delegate* unmanaged)&_ThrowExceptionForJitResult; + callbacks[107] = (delegate* unmanaged)&_ThrowExceptionForHelper; + callbacks[108] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[109] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[110] = (delegate* unmanaged)&_getEEInfo; + callbacks[111] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[112] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[113] = (delegate* unmanaged)&_getMethodName; + callbacks[114] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[115] = (delegate* unmanaged)&_getMethodHash; + callbacks[116] = (delegate* unmanaged)&_findNameOfToken; + callbacks[117] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[118] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[119] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[120] = (delegate* unmanaged)&_getInlinedCallFrameVptr; + callbacks[121] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[122] = (delegate* unmanaged)&_getHelperFtn; + callbacks[123] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[124] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[125] = (delegate* unmanaged)&_getMethodSync; + callbacks[126] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[127] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[128] = (delegate* unmanaged)&_embedClassHandle; + callbacks[129] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[130] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[131] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[132] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[133] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[134] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[135] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[136] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[137] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[138] = (delegate* unmanaged)&_getCallInfo; + callbacks[139] = (delegate* unmanaged)&_canAccessFamily; + callbacks[140] = (delegate* unmanaged)&_isRIDClassDomainID; + callbacks[141] = (delegate* unmanaged)&_getClassDomainID; + callbacks[142] = (delegate* unmanaged)&_getFieldAddress; + callbacks[143] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[144] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[145] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[146] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[147] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[148] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[149] = (delegate* unmanaged)&_addActiveDependency; + callbacks[150] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[151] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[152] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[153] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[154] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[155] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[156] = (delegate* unmanaged)&_allocMem; + callbacks[157] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[158] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[159] = (delegate* unmanaged)&_allocGCInfo; + callbacks[160] = (delegate* unmanaged)&_setEHcount; + callbacks[161] = (delegate* unmanaged)&_setEHinfo; + callbacks[162] = (delegate* unmanaged)&_logMsg; + callbacks[163] = (delegate* unmanaged)&_doAssert; + callbacks[164] = (delegate* unmanaged)&_reportFatalError; + callbacks[165] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[166] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[167] = (delegate* unmanaged)&_recordCallSite; + callbacks[168] = (delegate* unmanaged)&_recordRelocation; + callbacks[169] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[170] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[171] = (delegate* unmanaged)&_getJitFlags; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index 3bb774ed11b50..b6d7649864b99 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -286,14 +286,9 @@ public enum CorInfoHelpFunc CORINFO_HELP_STACK_PROBE, // Probes each page of the allocated stack frame CORINFO_HELP_PATCHPOINT, // Notify runtime that code has reached a patchpoint - CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, // Notify runtime that code has reached a part of the method that wasn't originally jitted. - CORINFO_HELP_CLASSPROFILE32, // Update 32-bit class profile for a call site CORINFO_HELP_CLASSPROFILE64, // Update 64-bit class profile for a call site - CORINFO_HELP_DELEGATEPROFILE32, // Update 32-bit method profile for a delegate call site - CORINFO_HELP_DELEGATEPROFILE64, // Update 64-bit method profile for a delegate call site - CORINFO_HELP_VTABLEPROFILE32, // Update 32-bit method profile for a vtable call site - CORINFO_HELP_VTABLEPROFILE64, // Update 64-bit method profile for a vtable call site + CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, // Notify runtime that code has reached a part of the method that wasn't originally jitted. CORINFO_HELP_VALIDATE_INDIRECT_CALL, // CFG: Validate function pointer CORINFO_HELP_DISPATCH_INDIRECT_CALL, // CFG: Validate and dispatch to pointer diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 27dbbfb44b9f8..bb822b4655506 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -101,23 +101,20 @@ public static IntPtr Get() private static readonly IntPtr s_jit; } - private struct LikelyClassMethodRecord + private struct LikelyClassRecord { - public IntPtr handle; + public IntPtr clsHandle; public uint likelihood; - public LikelyClassMethodRecord(IntPtr handle, uint likelihood) + public LikelyClassRecord(IntPtr clsHandle, uint likelihood) { - this.handle = handle; + this.clsHandle = clsHandle; this.likelihood = likelihood; } } [DllImport(JitLibrary)] - private extern static uint getLikelyClasses(LikelyClassMethodRecord* pLikelyClasses, uint maxLikelyClasses, PgoInstrumentationSchema* schema, uint countSchemaItems, byte*pInstrumentationData, int ilOffset); - - [DllImport(JitLibrary)] - private extern static uint getLikelyMethods(LikelyClassMethodRecord* pLikelyMethods, uint maxLikelyMethods, PgoInstrumentationSchema* schema, uint countSchemaItems, byte*pInstrumentationData, int ilOffset); + private extern static uint getLikelyClasses(LikelyClassRecord* pLikelyClasses, uint maxLikelyClasses, PgoInstrumentationSchema* schema, uint countSchemaItems, byte*pInstrumentationData, int ilOffset); [DllImport(JitSupportLibrary)] private extern static IntPtr GetJitHost(IntPtr configProvider); @@ -195,18 +192,17 @@ private Logger Logger public static IEnumerable ConvertTypeHandleHistogramsToCompactTypeHistogramFormat(PgoSchemaElem[] pgoData, CompilationModuleGroup compilationModuleGroup) { - bool hasHistogram = false; + bool hasTypeHistogram = false; foreach (var elem in pgoData) { - if (elem.InstrumentationKind == PgoInstrumentationKind.HandleHistogramTypes || - elem.InstrumentationKind == PgoInstrumentationKind.HandleHistogramMethods) + if (elem.InstrumentationKind == PgoInstrumentationKind.HandleHistogramTypes) { // found histogram - hasHistogram = true; + hasTypeHistogram = true; break; } } - if (!hasHistogram) + if (!hasTypeHistogram) { foreach (var elem in pgoData) { @@ -226,10 +222,9 @@ public static IEnumerable ConvertTypeHandleHistogramsToCompactTyp if ((i + 1 < pgoData.Length) && (pgoData[i].InstrumentationKind == PgoInstrumentationKind.HandleHistogramIntCount || pgoData[i].InstrumentationKind == PgoInstrumentationKind.HandleHistogramLongCount) && - (pgoData[i + 1].InstrumentationKind == PgoInstrumentationKind.HandleHistogramTypes || - pgoData[i + 1].InstrumentationKind == PgoInstrumentationKind.HandleHistogramMethods)) + (pgoData[i + 1].InstrumentationKind == PgoInstrumentationKind.HandleHistogramTypes)) { - PgoSchemaElem? newElem = ComputeLikelyClassMethod(i, handleToObject, nativeSchema, instrumentationData, compilationModuleGroup); + PgoSchemaElem? newElem = ComputeLikelyClass(i, handleToObject, nativeSchema, instrumentationData, compilationModuleGroup); if (newElem.HasValue) { yield return newElem.Value; @@ -254,63 +249,33 @@ IntPtr LocalObjectToHandle(object input) } } - private static PgoSchemaElem? ComputeLikelyClassMethod(int index, Dictionary handleToObject, PgoInstrumentationSchema[] nativeSchema, byte[] instrumentationData, CompilationModuleGroup compilationModuleGroup) + private static PgoSchemaElem? ComputeLikelyClass(int index, Dictionary handleToObject, PgoInstrumentationSchema[] nativeSchema, byte[] instrumentationData, CompilationModuleGroup compilationModuleGroup) { // getLikelyClasses will use two entries from the native schema table. There must be at least two present to avoid overruning the buffer if (index > (nativeSchema.Length - 2)) return null; - bool isType = nativeSchema[index + 1].InstrumentationKind == PgoInstrumentationKind.HandleHistogramTypes; - fixed(PgoInstrumentationSchema* pSchema = &nativeSchema[index]) { fixed(byte* pInstrumentationData = &instrumentationData[0]) { - // We're going to store only the most popular type/method to reduce size of the profile - LikelyClassMethodRecord* likelyClassMethods = stackalloc LikelyClassMethodRecord[1]; - uint numberOfRecords; - if (isType) - { - numberOfRecords = getLikelyClasses(likelyClassMethods, 1, pSchema, 2, pInstrumentationData, nativeSchema[index].ILOffset); - } - else - { - numberOfRecords = getLikelyMethods(likelyClassMethods, 1, pSchema, 2, pInstrumentationData, nativeSchema[index].ILOffset); - } + // We're going to store only the most popular type to reduce size of the profile + LikelyClassRecord* likelyClasses = stackalloc LikelyClassRecord[1]; + uint numberOfClasses = getLikelyClasses(likelyClasses, 1, pSchema, 2, pInstrumentationData, nativeSchema[index].ILOffset); - if (numberOfRecords > 0) + if (numberOfClasses > 0) { - TypeSystemEntityOrUnknown[] newData = null; - if (isType) - { - TypeDesc type = (TypeDesc)handleToObject[likelyClassMethods->handle]; -#if READYTORUN - if (compilationModuleGroup.VersionsWithType(type)) -#endif - { - newData = new[] { new TypeSystemEntityOrUnknown(type) }; - } - } - else - { - MethodDesc method = (MethodDesc)handleToObject[likelyClassMethods->handle]; - + TypeDesc type = (TypeDesc)handleToObject[likelyClasses->clsHandle]; #if READYTORUN - if (compilationModuleGroup.VersionsWithMethodBody(method)) + if (compilationModuleGroup.VersionsWithType(type)) #endif - { - newData = new[] { new TypeSystemEntityOrUnknown(method) }; - } - } - - if (newData != null) { PgoSchemaElem likelyClassElem = new PgoSchemaElem(); - likelyClassElem.InstrumentationKind = isType ? PgoInstrumentationKind.GetLikelyClass : PgoInstrumentationKind.GetLikelyMethod; + likelyClassElem.InstrumentationKind = PgoInstrumentationKind.GetLikelyClass; likelyClassElem.ILOffset = nativeSchema[index].ILOffset; likelyClassElem.Count = 1; - likelyClassElem.Other = (int)(likelyClassMethods->likelihood | (numberOfRecords << 8)); - likelyClassElem.DataObject = newData; + likelyClassElem.Other = (int)(likelyClasses->likelihood | (numberOfClasses << 8)); + likelyClassElem.DataObject = new TypeSystemEntityOrUnknown[] { new TypeSystemEntityOrUnknown(type) }; return likelyClassElem; } } @@ -466,18 +431,7 @@ private void PublishCode() _methodCodeNode.InitializeDebugLocInfos(_debugLocInfos); _methodCodeNode.InitializeDebugVarInfos(_debugVarInfos); #if READYTORUN - MethodDesc[] inlineeArray; - if (_inlinedMethods != null) - { - inlineeArray = new MethodDesc[_inlinedMethods.Count]; - _inlinedMethods.CopyTo(inlineeArray); - Array.Sort(inlineeArray, TypeSystemComparer.Instance.Compare); - } - else - { - inlineeArray = Array.Empty(); - } - _methodCodeNode.InitializeInliningInfo(inlineeArray, _compilation.NodeFactory); + _methodCodeNode.InitializeInliningInfo(_inlinedMethods.ToArray(), _compilation.NodeFactory); // Detect cases where the instruction set support used is a superset of the baseline instruction set specification var baselineSupport = _compilation.InstructionSetSupport; @@ -506,20 +460,7 @@ private void PublishCode() InstructionSetSupport actualSupport = new InstructionSetSupport(_actualInstructionSetSupported, _actualInstructionSetUnsupported, architecture); var node = _compilation.SymbolNodeFactory.PerMethodInstructionSetSupportFixup(actualSupport); - AddPrecodeFixup(node); - } - - Debug.Assert(_stashedPrecodeFixups.Count == 0); - if (_precodeFixups != null) - { - HashSet computedNodes = new HashSet(); - foreach (var fixup in _precodeFixups) - { - if (computedNodes.Add(fixup)) - { - _methodCodeNode.Fixups.Add(fixup); - } - } + _methodCodeNode.Fixups.Add(node); } #else var methodIL = (MethodIL)HandleToObject((IntPtr)_methodScope); @@ -625,12 +566,9 @@ private void CompileMethodCleanup() _lastException = null; #if READYTORUN - _inlinedMethods = null; + _inlinedMethods = new ArrayBuilder(); _actualInstructionSetSupported = default(InstructionSetFlags); _actualInstructionSetUnsupported = default(InstructionSetFlags); - _precodeFixups = null; - _stashedPrecodeFixups.Clear(); - _stashedInlinedMethods.Clear(); #endif _instantiationToJitVisibleInstantiation = null; @@ -1443,7 +1381,7 @@ private bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info) if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout) { ISymbolNode virtualResolutionNode = _compilation.SymbolNodeFactory.CheckVirtualFunctionOverride(methodWithTokenDecl, objType, methodWithTokenImpl); - AddPrecodeFixup(virtualResolutionNode); + _methodCodeNode.Fixups.Add(virtualResolutionNode); } #endif info->detail = CORINFO_DEVIRTUALIZATION_DETAIL.CORINFO_DEVIRTUALIZATION_SUCCESS; @@ -2146,7 +2084,7 @@ private uint getClassSize(CORINFO_CLASS_STRUCT_* cls) if (NeedsTypeLayoutCheck(type)) { ISymbolNode node = _compilation.SymbolNodeFactory.CheckTypeLayout(type); - AddPrecodeFixup(node); + _methodCodeNode.Fixups.Add(node); } #endif return (uint)classSize.AsInt; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 1f65d5e5f8354..9a173957fa007 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -478,11 +478,7 @@ public enum CorInfoClassId } public enum CorInfoInline { - INLINE_PASS = 0, // Inlining OK - INLINE_PREJIT_SUCCESS = 1, // Inline check for prejit checking usage succeeded - INLINE_CHECK_CAN_INLINE_SUCCESS = 2, // JIT detected it is permitted to try to actually inline - INLINE_CHECK_CAN_INLINE_VMFAIL = 3, // VM specified that inline must fail via the CanInline api - + INLINE_PASS = 0, // Inlining OK // failures are negative INLINE_FAIL = -1, // Inlining not OK for this case only diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index f1393ad2095a7..45fcdef14faaf 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -159,7 +159,6 @@ FUNCTIONS void getMethodSig( CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig, CORINFO_CLASS_HANDLE memberParent ); bool getMethodInfo( CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info ); CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd); - void beginInlining(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd); void reportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char * reason); bool canTailCall( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE declaredCalleeHnd, CORINFO_METHOD_HANDLE exactCalleeHnd, bool fIsTailPrefix ); void reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char * reason); diff --git a/src/coreclr/tools/Common/Pgo/PgoFormat.cs b/src/coreclr/tools/Common/Pgo/PgoFormat.cs index 5dc847b34810b..a4e23286be4c6 100644 --- a/src/coreclr/tools/Common/Pgo/PgoFormat.cs +++ b/src/coreclr/tools/Common/Pgo/PgoFormat.cs @@ -49,7 +49,6 @@ public enum PgoInstrumentationKind EdgeIntCount = (DescriptorMin * 6) | FourByte, // edge counter using unsigned 4 byte int EdgeLongCount = (DescriptorMin * 6) | EightByte, // edge counter using unsigned 8 byte int GetLikelyClass = (DescriptorMin * 7) | TypeHandle, // Compressed get likely class data - GetLikelyMethod = (DescriptorMin * 7) | MethodHandle, // Compressed get likely method data } public interface IPgoSchemaDataLoader diff --git a/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs b/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs index 838dd7038d33b..c537f6ea4571e 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs @@ -233,7 +233,7 @@ private void SetFieldLayout(List fieldLayoutInterval, int o previousInterval.EndSentinel = newInterval.EndSentinel; fieldLayoutInterval[newIntervalLocation - 1] = previousInterval; - newIntervalLocation--; + newIntervalLocation = newIntervalLocation - 1; } else { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldDesc.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldDesc.cs index 23bd5ba923a54..ad44d48574795 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/FieldDesc.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldDesc.cs @@ -45,9 +45,6 @@ public virtual string Name get; } - // Get the embedded signature data used to hold custom modifiers and such within a field signature - public abstract EmbeddedSignatureData[] GetEmbeddedSignatureData(); - public abstract bool IsStatic { get; diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldForInstantiatedType.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldForInstantiatedType.cs index fbc456a830639..b51d55660a686 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/FieldForInstantiatedType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldForInstantiatedType.cs @@ -51,11 +51,6 @@ public override TypeDesc FieldType } } - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() - { - return _fieldDef.GetEmbeddedSignatureData(); - } - public override bool IsStatic { get diff --git a/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs b/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs index bed4e2388e92a..f1164b677e20a 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/InstantiatedType.cs @@ -273,7 +273,7 @@ public override TypeDesc InstantiateSignature(Instantiation typeInstantiation, I } } - return clone ?? uninstantiatedTypes; + return clone != null ? clone : uninstantiatedTypes; } // Strips instantiation. E.g C -> C diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeHashingAlgorithms.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeHashingAlgorithms.cs index 5904397c4a015..6b3d37851cee6 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TypeHashingAlgorithms.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeHashingAlgorithms.cs @@ -125,7 +125,7 @@ private static string IntToString(int arg) while (arg != 0) { sb.Append((char)('0' + (arg % 10))); - arg /= 10; + arg = arg / 10; } // Reverse the string diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaField.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaField.cs index 6ba7907106dd6..b6d5e4fd41f8b 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaField.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaField.cs @@ -113,19 +113,6 @@ public override TypeDesc FieldType } } - // This is extremely rarely needed. Don't cache it at all. - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() - { - var metadataReader = MetadataReader; - BlobReader signatureReader = metadataReader.GetBlobReader(metadataReader.GetFieldDefinition(_handle).Signature); - - EcmaSignatureParser parser = new EcmaSignatureParser(Module, signatureReader, NotFoundBehavior.Throw); - var fieldType = parser.ParseFieldSignature(out var embeddedSig); - Debug.Assert(fieldType == FieldType); - return embeddedSig; - } - - [MethodImpl(MethodImplOptions.NoInlining)] private int InitializeFieldFlags(int mask) { diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs index f2530ec8b19d7..2247f551fc29d 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaSignatureParser.cs @@ -471,25 +471,6 @@ public TypeDesc ParseFieldSignature() return ParseType(); } - public TypeDesc ParseFieldSignature(out EmbeddedSignatureData[] embeddedSigData) - { - try - { - _indexStack = new Stack(); - _indexStack.Push(1); - _indexStack.Push(0); - _embeddedSignatureDataList = new List(); - TypeDesc parsedType = ParseFieldSignature(); - embeddedSigData = _embeddedSignatureDataList.Count == 0 ? null : _embeddedSignatureDataList.ToArray(); - return parsedType; - } - finally - { - _indexStack = null; - _embeddedSignatureDataList = null; - } - } - public LocalVariableDefinition[] ParseLocalsSignature() { if (_reader.ReadSignatureHeader().Kind != SignatureKind.LocalVariables) diff --git a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs index 2b3b625db32d1..073cb7a4fdfb2 100644 --- a/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Ecma/EcmaType.cs @@ -374,12 +374,7 @@ public override MethodDesc GetDefaultConstructor() && stringComparer.Equals(methodDefinition.Name, ".ctor")) { var method = (EcmaMethod)_module.GetObject(handle); - MethodSignature sig = method.Signature; - - if (sig.Length != 0) - continue; - - if ((sig.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) == MethodSignatureFlags.CallingConventionVarargs) + if (method.Signature.Length != 0) continue; return method; diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs index 5b49bfdb50faa..c2a44b01653a5 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs @@ -56,8 +56,6 @@ public override TypeDesc FieldType } } - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() => null; - public override bool HasRva { get diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/InlineArrayType.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/InlineArrayType.cs index 51ac01f9a2fb6..4cf06e8b6bfb4 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/InlineArrayType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/InlineArrayType.cs @@ -441,7 +441,6 @@ public override TypeDesc FieldType return _owningType.ElementType; } } - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() => null; public override bool HasRva { diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/NativeStructType.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/NativeStructType.cs index 149987476b3a3..bf5e0c6ef3d7b 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/NativeStructType.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/NativeStructType.cs @@ -348,8 +348,6 @@ public override TypeDesc FieldType } } - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() => null; - public override bool HasRva { get diff --git a/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs b/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs index 46110f26bb2a8..5a47094605c9e 100644 --- a/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs +++ b/src/coreclr/tools/Common/TypeSystem/MetadataEmitter/TypeSystemMetadataEmitter.cs @@ -18,18 +18,14 @@ class TypeSystemMetadataEmitter MetadataBuilder _metadataBuilder; BlobBuilder _ilBuilder; MethodBodyStreamEncoder _methodBodyStream; - Dictionary _assemblyRefNameHandles = new Dictionary(); Dictionary _assemblyRefs = new Dictionary(); Dictionary _typeRefs = new Dictionary(); Dictionary _methodRefs = new Dictionary(); - Dictionary _fieldRefs = new Dictionary(); Blob _mvidFixup; BlobHandle _noArgsVoidReturnStaticMethodSigHandle; - protected TypeSystemContext _typeSystemContext; - public TypeSystemMetadataEmitter(AssemblyName assemblyName, TypeSystemContext context, AssemblyFlags flags = default(AssemblyFlags), byte[] publicKeyArray = null, AssemblyHashAlgorithm hashAlgorithm = AssemblyHashAlgorithm.None) + public TypeSystemMetadataEmitter(AssemblyName assemblyName, TypeSystemContext context, AssemblyFlags flags = default(AssemblyFlags)) { - _typeSystemContext = context; _metadataBuilder = new MetadataBuilder(); _ilBuilder = new BlobBuilder(); _methodBodyStream = new MethodBodyStreamEncoder(_ilBuilder); @@ -37,11 +33,21 @@ public TypeSystemMetadataEmitter(AssemblyName assemblyName, TypeSystemContext co if (assemblyName.CultureName != null) throw new ArgumentException("assemblyName"); + if (assemblyName.GetPublicKeyToken() != null) + throw new ArgumentException("assemblyName"); + var mvid = _metadataBuilder.ReserveGuid(); _mvidFixup = mvid.Content; _metadataBuilder.AddModule(0, assemblyNameHandle, mvid.Handle, default(GuidHandle), default(GuidHandle)); - _metadataBuilder.AddAssembly(assemblyNameHandle, assemblyName.Version ?? new Version(0,0,0,0), default(StringHandle), publicKey: publicKeyArray != null ? _metadataBuilder.GetOrAddBlob(publicKeyArray) : default(BlobHandle), flags, AssemblyHashAlgorithm.None); + _metadataBuilder.AddAssembly(assemblyNameHandle, assemblyName.Version ?? new Version(0,0,0,0), default(StringHandle), default(BlobHandle), flags, AssemblyHashAlgorithm.None); + + var canonAssemblyNameHandle = _metadataBuilder.GetOrAddString("System.Private.Canon"); + var canonAssemblyRef = _metadataBuilder.AddAssemblyReference(canonAssemblyNameHandle, new Version(0, 0, 0, 0), default(StringHandle), default(BlobHandle), (AssemblyFlags)0, default(BlobHandle)); + var systemStringHandle = _metadataBuilder.GetOrAddString("System"); + var canonStringHandle = _metadataBuilder.GetOrAddString("__Canon"); + var canonTypeRef = _metadataBuilder.AddTypeReference(canonAssemblyRef, systemStringHandle, canonStringHandle); + _typeRefs.Add(context.CanonType, canonTypeRef); _metadataBuilder.AddTypeDefinition( default(TypeAttributes), @@ -50,20 +56,7 @@ public TypeSystemMetadataEmitter(AssemblyName assemblyName, TypeSystemContext co baseType: default(EntityHandle), fieldList: MetadataTokens.FieldDefinitionHandle(1), methodList: MetadataTokens.MethodDefinitionHandle(1)); - } - public void InjectSystemPrivateCanon() - { - var canonAssemblyNameHandle = _metadataBuilder.GetOrAddString("System.Private.Canon"); - var canonAssemblyRef = _metadataBuilder.AddAssemblyReference(canonAssemblyNameHandle, new Version(0, 0, 0, 0), default(StringHandle), default(BlobHandle), (AssemblyFlags)0, default(BlobHandle)); - var systemStringHandle = _metadataBuilder.GetOrAddString("System"); - var canonStringHandle = _metadataBuilder.GetOrAddString("__Canon"); - var canonTypeRef = _metadataBuilder.AddTypeReference(canonAssemblyRef, systemStringHandle, canonStringHandle); - _typeRefs.Add(_typeSystemContext.CanonType, canonTypeRef); - } - - public void AllowUseOfAddGlobalMethod() - { BlobBuilder noArgsNoReturnStaticMethodSig = new BlobBuilder(); BlobEncoder signatureEncoder = new BlobEncoder(noArgsNoReturnStaticMethodSig); @@ -86,8 +79,6 @@ public MethodDefinitionHandle AddGlobalMethod(string name, InstructionEncoder il private static readonly Guid s_guid = new Guid("97F4DBD4-F6D1-4FAD-91B3-1001F92068E5"); private static readonly BlobContentId s_contentId = new BlobContentId(s_guid, 0x04030201); - public MetadataBuilder Builder => _metadataBuilder; - public void SerializeToStream(Stream peStream) { var peHeaderBuilder = new PEHeaderBuilder(); @@ -100,47 +91,6 @@ public void SerializeToStream(Stream peStream) peBlob.WriteContentTo(peStream); } - // Generate only the metadata blob as a byte[] - public byte[] EmitToMetadataBlob() - { - MetadataRootBuilder metadataRootBuilder = new MetadataRootBuilder(_metadataBuilder); - BlobBuilder metadataBlobBuilder = new BlobBuilder(); - metadataRootBuilder.Serialize(metadataBlobBuilder, methodBodyStreamRva: 0, mappedFieldDataStreamRva: 0); - - // Clear some variables to catch any caller trying to emit data after writing the output file - _metadataBuilder = null; - - return metadataBlobBuilder.ToArray(); - } - - public AssemblyReferenceHandle GetAssemblyRef(AssemblyName name) - { - if (!_assemblyRefNameHandles.TryGetValue(name.FullName, out var handle)) - { - StringHandle assemblyName = _metadataBuilder.GetOrAddString(name.Name); - StringHandle cultureName = (name.CultureName != null) ? _metadataBuilder.GetOrAddString(name.CultureName) : default(StringHandle); - BlobHandle publicTokenBlob = name.GetPublicKeyToken() != null ? _metadataBuilder.GetOrAddBlob(name.GetPublicKeyToken()) : default(BlobHandle); - AssemblyFlags flags = default(AssemblyFlags); - if (name.Flags.HasFlag(AssemblyNameFlags.Retargetable)) - { - flags |= AssemblyFlags.Retargetable; - } - if (name.ContentType == AssemblyContentType.WindowsRuntime) - { - flags |= AssemblyFlags.WindowsRuntime; - } - - Version version = name.Version; - if (version == null) - version = new Version(0, 0); - - handle = _metadataBuilder.AddAssemblyReference(assemblyName, version, cultureName, publicTokenBlob, flags, default(BlobHandle)); - - _assemblyRefNameHandles[name.FullName] = handle; - } - return handle; - } - public AssemblyReferenceHandle GetAssemblyRef(IAssemblyDesc assemblyDesc) { if (_assemblyRefs.TryGetValue(assemblyDesc, out var handle)) @@ -148,50 +98,26 @@ public AssemblyReferenceHandle GetAssemblyRef(IAssemblyDesc assemblyDesc) return handle; } AssemblyName name = assemblyDesc.GetName(); - var referenceHandle = GetAssemblyRef(name); - _assemblyRefs.Add(assemblyDesc, referenceHandle); - return referenceHandle; - } - - public EntityHandle EmitMetadataHandleForTypeSystemEntity(TypeSystemEntity entity) - { - switch (entity) + StringHandle assemblyName = _metadataBuilder.GetOrAddString(name.Name); + StringHandle cultureName = (name.CultureName != null) ? _metadataBuilder.GetOrAddString(name.CultureName) : default(StringHandle); + BlobHandle publicTokenBlob = name.GetPublicKeyToken() != null ? _metadataBuilder.GetOrAddBlob(name.GetPublicKeyToken()) : default(BlobHandle); + AssemblyFlags flags = default(AssemblyFlags); + if (name.Flags.HasFlag(AssemblyNameFlags.Retargetable)) { - case FieldDesc field: return GetFieldRef(field); - case MethodDesc method: return GetMethodRef(method); - case TypeDesc type: return GetTypeRef(type); - case ModuleDesc assembly: return GetAssemblyRef(assembly.Assembly); - case MethodSignature methodSignature: return GetStandaloneSig(methodSignature); - - default: - throw new NotSupportedException(); + flags |= AssemblyFlags.Retargetable; } - } - - public IEnumerable> TypeSystemEntitiesKnown - { - get + if (name.ContentType == AssemblyContentType.WindowsRuntime) { - foreach (var item in _typeRefs) - { - yield return new KeyValuePair(item.Key, item.Value); - } - - foreach (var item in _methodRefs) - { - yield return new KeyValuePair(item.Key, item.Value); - } - - foreach (var item in _fieldRefs) - { - yield return new KeyValuePair(item.Key, item.Value); - } + flags |= AssemblyFlags.WindowsRuntime; } - } - protected virtual EntityHandle GetNonNestedResolutionScope(MetadataType metadataType) - { - return GetAssemblyRef(metadataType.Module.Assembly); + Version version = name.Version; + if (version == null) + version = new Version(0, 0); + + var referenceHandle = _metadataBuilder.AddAssemblyReference(assemblyName, version, cultureName, publicTokenBlob, flags, default(BlobHandle)); + _assemblyRefs.Add(assemblyDesc, referenceHandle); + return referenceHandle; } public EntityHandle GetTypeRef(TypeDesc type) @@ -218,7 +144,7 @@ public EntityHandle GetTypeRef(TypeDesc type) if (metadataType.ContainingType == null) { // non-nested type - resolutionScope = GetNonNestedResolutionScope(metadataType); + resolutionScope = GetAssemblyRef(metadataType.Module.Assembly); } else { @@ -240,58 +166,6 @@ public EntityHandle GetTypeRef(TypeDesc type) return typeHandle; } - private BlobHandle GetMethodSignatureBlobHandle(MethodSignature sig) - { - EmbeddedSignatureDataEmitter signatureDataEmitter; - if (sig.HasEmbeddedSignatureData) - { - signatureDataEmitter = new EmbeddedSignatureDataEmitter(sig.GetEmbeddedSignatureData(), this); - } - else - { - signatureDataEmitter = EmbeddedSignatureDataEmitter.EmptySingleton; - } - - BlobBuilder memberRefSig = new BlobBuilder(); - EncodeMethodSignature(memberRefSig, sig, signatureDataEmitter); - - if (!signatureDataEmitter.Complete) - throw new ArgumentException(); - - var sigBlob = _metadataBuilder.GetOrAddBlob(memberRefSig); - return sigBlob; - } - - private BlobHandle GetFieldSignatureBlobHandle(FieldDesc field) - { - var fieldDef = field.GetTypicalFieldDefinition(); - var embeddedSigData = field.GetEmbeddedSignatureData(); - EmbeddedSignatureDataEmitter signatureDataEmitter; - if (embeddedSigData != null && embeddedSigData.Length != 0) - { - signatureDataEmitter = new EmbeddedSignatureDataEmitter(embeddedSigData, this); - } - else - { - signatureDataEmitter = EmbeddedSignatureDataEmitter.EmptySingleton; - } - - BlobBuilder memberRefSig = new BlobBuilder(); - EncodeFieldSignature(memberRefSig, field.FieldType, signatureDataEmitter); - - if (!signatureDataEmitter.Complete) - throw new ArgumentException(); - - var sigBlob = _metadataBuilder.GetOrAddBlob(memberRefSig); - return sigBlob; - } - - public EntityHandle GetStandaloneSig(MethodSignature sig) - { - var sigBlob = GetMethodSignatureBlobHandle(sig); - return _metadataBuilder.AddStandaloneSignature(sigBlob); - } - public EntityHandle GetMethodRef(MethodDesc method) { if (_methodRefs.TryGetValue(method, out var handle)) @@ -318,8 +192,24 @@ public EntityHandle GetMethodRef(MethodDesc method) EntityHandle typeHandle = GetTypeRef((MetadataType)method.OwningType); StringHandle methodName = _metadataBuilder.GetOrAddString(method.Name); var sig = method.GetTypicalMethodDefinition().Signature; - var sigBlob = GetMethodSignatureBlobHandle(sig); + EmbeddedSignatureDataEmitter signatureDataEmitter; + if (sig.HasEmbeddedSignatureData) + { + signatureDataEmitter = new EmbeddedSignatureDataEmitter(sig.GetEmbeddedSignatureData(), this); + } + else + { + signatureDataEmitter = EmbeddedSignatureDataEmitter.EmptySingleton; + } + + BlobBuilder memberRefSig = new BlobBuilder(); + EncodeMethodSignature(memberRefSig, sig, signatureDataEmitter); + + if (!signatureDataEmitter.Complete) + throw new ArgumentException(); + + var sigBlob = _metadataBuilder.GetOrAddBlob(memberRefSig); methodHandle = _metadataBuilder.AddMemberReference(typeHandle, methodName, sigBlob); } @@ -327,25 +217,6 @@ public EntityHandle GetMethodRef(MethodDesc method) return methodHandle; } - public EntityHandle GetFieldRef(FieldDesc field) - { - if (_fieldRefs.TryGetValue(field, out var handle)) - { - return handle; - } - - EntityHandle fieldHandle; - - EntityHandle typeHandle = GetTypeRef((MetadataType)field.OwningType); - StringHandle fieldName = _metadataBuilder.GetOrAddString(field.Name); - - var sigBlob = GetFieldSignatureBlobHandle(field.GetTypicalFieldDefinition()); - fieldHandle = _metadataBuilder.AddMemberReference(typeHandle, fieldName, sigBlob); - - _fieldRefs.Add(field, fieldHandle); - return fieldHandle; - } - private void EncodeType(BlobBuilder blobBuilder, TypeDesc type, EmbeddedSignatureDataEmitter signatureDataEmitter) { signatureDataEmitter.Push(); @@ -672,15 +543,6 @@ void EncodeMethodSignature(BlobBuilder signatureBuilder, MethodSignature sig, Em signatureDataEmitter.Pop(); } - void EncodeFieldSignature(BlobBuilder signatureBuilder, TypeDesc fieldType, EmbeddedSignatureDataEmitter signatureDataEmitter) - { - signatureDataEmitter.Push(); - BlobEncoder signatureEncoder = new BlobEncoder(signatureBuilder); - signatureEncoder.FieldSignature(); - EncodeType(signatureBuilder, fieldType, signatureDataEmitter); - signatureDataEmitter.Pop(); - } - public UserStringHandle GetUserStringHandle(string userString) { return _metadataBuilder.GetOrAddUserString(userString); diff --git a/src/coreclr/tools/aot/.editorconfig b/src/coreclr/tools/aot/.editorconfig index f5e97a5d50a0d..5f1bbfd242997 100644 --- a/src/coreclr/tools/aot/.editorconfig +++ b/src/coreclr/tools/aot/.editorconfig @@ -27,84 +27,3 @@ dotnet_sort_system_directives_first = true csharp_style_expression_bodied_properties = true:none csharp_style_expression_bodied_indexers = true:none csharp_style_expression_bodied_accessors = true:none - -[Mono.Linker.Tests/**.cs] -indent_style = tab -indent_size = 4 -csharp_new_line_before_open_brace = types,methods -csharp_new_line_before_else = false -csharp_new_line_before_catch = false -csharp_new_line_before_finally = false -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true - -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_between_method_declaration_name_and_open_parenthesis = true -csharp_space_between_method_call_name_and_opening_parenthesis = true -csharp_space_before_open_square_brackets = false -csharp_space_after_cast = true - -csharp_indent_switch_labels = false - -# Sort using and Import directives with System.* appearing first -dotnet_sort_system_directives_first = true - -# Prefer property-like constructs to have an expression-body -csharp_style_expression_bodied_properties = true:none -csharp_style_expression_bodied_indexers = true:none -csharp_style_expression_bodied_accessors = true:none - -[Mono.Linker.Tests.Cases/**.cs] -indent_style = tab -indent_size = 4 -csharp_new_line_before_open_brace = types,methods -csharp_new_line_before_else = false -csharp_new_line_before_catch = false -csharp_new_line_before_finally = false -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true - -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_between_method_declaration_name_and_open_parenthesis = true -csharp_space_between_method_call_name_and_opening_parenthesis = true -csharp_space_before_open_square_brackets = false -csharp_space_after_cast = true - -csharp_indent_switch_labels = false - -# Sort using and Import directives with System.* appearing first -dotnet_sort_system_directives_first = true - -# Prefer property-like constructs to have an expression-body -csharp_style_expression_bodied_properties = true:none -csharp_style_expression_bodied_indexers = true:none -csharp_style_expression_bodied_accessors = true:none - -[Mono.Linker.Tests.Cases.Expectations/**.cs] -indent_style = tab -indent_size = 4 -csharp_new_line_before_open_brace = types,methods -csharp_new_line_before_else = false -csharp_new_line_before_catch = false -csharp_new_line_before_finally = false -csharp_new_line_before_members_in_object_initializers = true -csharp_new_line_before_members_in_anonymous_types = true -csharp_new_line_between_query_expression_clauses = true - -csharp_space_after_keywords_in_control_flow_statements = true -csharp_space_between_method_declaration_name_and_open_parenthesis = true -csharp_space_between_method_call_name_and_opening_parenthesis = true -csharp_space_before_open_square_brackets = false -csharp_space_after_cast = true - -csharp_indent_switch_labels = false - -# Sort using and Import directives with System.* appearing first -dotnet_sort_system_directives_first = true - -# Prefer property-like constructs to have an expression-body -csharp_style_expression_bodied_properties = true:none -csharp_style_expression_bodied_indexers = true:none -csharp_style_expression_bodied_accessors = true:none diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitution.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitution.cs deleted file mode 100644 index be138cefa7de1..0000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitution.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using Internal.IL; -using Internal.IL.Stubs; -using Internal.TypeSystem; - -namespace ILCompiler -{ - internal sealed class BodySubstitution - { - private object _value; - - private readonly static object Throw = new object(); - - public readonly static BodySubstitution ThrowingBody = new BodySubstitution(Throw); - public readonly static BodySubstitution EmptyBody = new BodySubstitution(null); - - public object Value - { - get - { - Debug.Assert(_value != Throw); - return _value; - } - } - - private BodySubstitution(object value) => _value = value; - - public static BodySubstitution Create(object value) => new BodySubstitution(value); - public MethodIL EmitIL(MethodDesc method) - { - ILEmitter emit = new ILEmitter(); - ILCodeStream codestream = emit.NewCodeStream(); - - if (_value == Throw) - { - codestream.EmitCallThrowHelper(emit, method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowFeatureBodyRemoved")); - } - else if (_value == null) - { - Debug.Assert(method.Signature.ReturnType.IsVoid); - codestream.Emit(ILOpcode.ret); - } - else - { - Debug.Assert(_value is int); - codestream.EmitLdc((int)_value); - codestream.Emit(ILOpcode.ret); - } - - return emit.Link(method); - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs deleted file mode 100644 index 3aade53731c65..0000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Reflection.Metadata; -using Internal.TypeSystem; -using System.Xml.XPath; -using System.Globalization; -using System.Linq; - -namespace ILCompiler -{ - internal sealed class BodySubstitutionsParser : ProcessLinkerXmlBase - { - private readonly Dictionary _methodSubstitutions; - private readonly Dictionary _fieldSubstitutions; - - private BodySubstitutionsParser(TypeSystemContext context, Stream documentStream, ManifestResource resource, ModuleDesc resourceAssembly, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) - : base(context, documentStream, resource, resourceAssembly, xmlDocumentLocation, featureSwitchValues) - { - _methodSubstitutions = new Dictionary(); - _fieldSubstitutions = new Dictionary(); - } - - protected override void ProcessAssembly(ModuleDesc assembly, XPathNavigator nav, bool warnOnUnresolvedTypes) - { - ProcessTypes(assembly, nav, warnOnUnresolvedTypes); - } - - // protected override TypeDesc? ProcessExportedType(ExportedType exported, ModuleDesc assembly, XPathNavigator nav) => null; - - protected override bool ProcessTypePattern(string fullname, ModuleDesc assembly, XPathNavigator nav) => false; - - protected override void ProcessType(TypeDesc type, XPathNavigator nav) - { - Debug.Assert(ShouldProcessElement(nav)); - ProcessTypeChildren(type, nav); - } - - protected override void ProcessMethod(TypeDesc type, XPathNavigator methodNav, object customData) - { - string signature = GetSignature(methodNav); - if (string.IsNullOrEmpty(signature)) - return; - - MethodDesc method = FindMethod(type, signature); - if (method == null) - { - // LogWarning(methodNav, DiagnosticId.XmlCouldNotFindMethodOnType, signature, type.GetDisplayName()); - return; - } - - string action = GetAttribute(methodNav, "body"); - switch (action) - { - case "remove": - _methodSubstitutions.Add(method, BodySubstitution.ThrowingBody); - break; - case "stub": - BodySubstitution stubBody; - if (method.Signature.ReturnType.IsVoid) - stubBody = BodySubstitution.EmptyBody; - else - stubBody = BodySubstitution.Create(TryCreateSubstitution(method.Signature.ReturnType, GetAttribute(methodNav, "value"))); - - if (stubBody != null) - { - _methodSubstitutions[method] = stubBody; - } - else - { - // Context.LogWarning ($"Invalid value for '{method.GetDisplayName ()}' stub", 2010, _xmlDocumentLocation); - } - break; - default: - //Context.LogWarning($"Unknown body modification '{action}' for '{method.GetDisplayName()}'", 2011, _xmlDocumentLocation); - break; - } - } - - protected override void ProcessField(TypeDesc type, XPathNavigator fieldNav) - { - string name = GetAttribute(fieldNav, "name"); - if (string.IsNullOrEmpty(name)) - return; - - var field = type.GetFields().FirstOrDefault(f => f.Name == name); - if (field == null) - { - // LogWarning(fieldNav, DiagnosticId.XmlCouldNotFindFieldOnType, name, type.GetDisplayName()); - return; - } - - if (!field.IsStatic || field.IsLiteral) - { - // LogWarning(fieldNav, DiagnosticId.XmlSubstitutedFieldNeedsToBeStatic, field.GetDisplayName()); - return; - } - - string value = GetAttribute(fieldNav, "value"); - if (string.IsNullOrEmpty(value)) - { - //Context.LogWarning($"Missing 'value' attribute for field '{field.GetDisplayName()}'.", 2014, _xmlDocumentLocation); - return; - } - - object substitution = TryCreateSubstitution(field.FieldType, value); - if (substitution == null) - { - //Context.LogWarning($"Invalid value '{value}' for '{field.GetDisplayName()}'.", 2015, _xmlDocumentLocation); - return; - } - - if (String.Equals(GetAttribute(fieldNav, "initialize"), "true", StringComparison.InvariantCultureIgnoreCase)) - { - // We would need to also mess with the cctor of the type to set the field to this value: - // - // * Linker will remove all stsfld instructions referencing this field from the cctor - // * It will place an explicit stsfld in front of the last "ret" instruction in the cctor - // - // This approach... has issues. - throw new NotSupportedException(); - } - - _fieldSubstitutions[field] = substitution; - } - - static MethodDesc FindMethod(TypeDesc type, string signature) - { - foreach (MethodDesc meth in type.GetMethods()) - if (signature == GetMethodSignature(meth, includeGenericParameters: true)) - return meth; - return null; - } - - private object TryCreateSubstitution(TypeDesc type, string value) - { - switch (type.UnderlyingType.Category) - { - case TypeFlags.Int32: - if (string.IsNullOrEmpty(value)) - return 0; - else if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int iresult)) - return iresult; - break; - - case TypeFlags.Boolean: - if (String.IsNullOrEmpty(value)) - return 0; - else if (bool.TryParse(value, out bool bvalue)) - return bvalue ? 1 : 0; - else - goto case TypeFlags.Int32; - - default: - throw new NotSupportedException(type.ToString()); - } - - return null; - } - - public static (Dictionary, Dictionary) GetSubstitutions(TypeSystemContext context, UnmanagedMemoryStream documentStream, ManifestResource resource, ModuleDesc resourceAssembly, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) - { - var rdr = new BodySubstitutionsParser(context, documentStream, resource, resourceAssembly, xmlDocumentLocation, featureSwitchValues); - rdr.ProcessXml(false); - return (rdr._methodSubstitutions, rdr._fieldSubstitutions); - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs index 53e443db74447..09d58311aee3a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs @@ -659,12 +659,5 @@ public sealed class ConstrainedCallInfo public readonly MethodDesc Method; public ConstrainedCallInfo(TypeDesc constrainedType, MethodDesc method) => (ConstrainedType, Method) = (constrainedType, method); - public int CompareTo(ConstrainedCallInfo other, TypeSystemComparer comparer) - { - int result = comparer.Compare(ConstrainedType, other.ConstrainedType); - if (result == 0) - result = comparer.Compare(Method, other.Method); - return result; - } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs index 70f3d523ed9e4..3b19dbfcf1ad2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs @@ -161,9 +161,7 @@ internal void MarkStaticConstructor(in MessageOrigin origin, TypeDesc type) { if (!type.IsGenericDefinition && !type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true) && type.HasStaticConstructor) { - // Mark the GC static base - it contains a pointer to the class constructor, but also info - // about whether the class constructor already executed and it's what is looked at at runtime. - _dependencies.Add(_factory.TypeNonGCStaticsSymbol((MetadataType)type), "RunClassConstructor reference"); + _dependencies.Add(_factory.CanonicalEntrypoint(type.GetStaticConstructor()), "RunClassConstructor reference"); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs index 18c5b082f60fe..f584f7c5b2023 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -597,12 +597,6 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet if (systemTypeValue.RepresentedType.Type.IsDefType) { _reflectionMarker.Dependencies.Add(_factory.StructMarshallingData((DefType)systemTypeValue.RepresentedType.Type), "Marshal API"); - if (intrinsicId == IntrinsicId.Marshal_PtrToStructure - && systemTypeValue.RepresentedType.Type.GetParameterlessConstructor() is MethodDesc ctorMethod - && !_factory.MetadataManager.IsReflectionBlocked(ctorMethod)) - { - _reflectionMarker.Dependencies.Add(_factory.ReflectableMethod(ctorMethod), "Marshal API"); - } } } else @@ -625,7 +619,7 @@ public override bool HandleCall(MethodIL callingMethodBody, MethodDesc calledMet && !systemTypeValue.RepresentedType.Type.IsGenericDefinition && !systemTypeValue.RepresentedType.Type.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) { - if (systemTypeValue.RepresentedType.Type.IsDelegate) + if (systemTypeValue.RepresentedType.Type.IsDefType) { _reflectionMarker.Dependencies.Add(_factory.DelegateMarshallingData((DefType)systemTypeValue.RepresentedType.Type), "Marshal API"); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs index e2df7d38798e3..845fe201486d3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs @@ -77,11 +77,6 @@ protected override ISymbolNode GetBaseTypeNode(NodeFactory factory) return _type.BaseType != null ? factory.NecessaryTypeSymbol(_type.BaseType.NormalizeInstantiation()) : null; } - protected override ISymbolNode GetNonNullableValueTypeArrayElementTypeNode(NodeFactory factory) - { - return factory.ConstructedTypeSymbol(((ArrayType)_type).ElementType); - } - protected override int GCDescSize { get diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs index be5ce0d0dc80b..4c5d630437a3b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -101,11 +101,6 @@ protected override ISymbolNode GetBaseTypeNode(NodeFactory factory) return _type.BaseType != null ? factory.ConstructedTypeSymbol(_type.BaseType) : null; } - protected override ISymbolNode GetNonNullableValueTypeArrayElementTypeNode(NodeFactory factory) - { - return factory.ConstructedTypeSymbol(((ArrayType)_type).ElementType); - } - protected override IEETypeNode GetInterfaceTypeNode(NodeFactory factory, TypeDesc interfaceType) { // The interface type will be visible to reflection and should be considered constructed. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs index 3a8a1438b2bf2..09111876ceca6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CustomAttributeBasedDependencyAlgorithm.cs @@ -168,8 +168,7 @@ private static bool AddDependenciesFromCustomAttributeBlob(DependencyList depend { if (decodedArgument.Kind == CustomAttributeNamedArgumentKind.Field) { - if (!AddDependenciesFromField(dependencies, factory, attributeType, decodedArgument.Name)) - return false; + // This is an instance field. We don't track them right now. } else { @@ -187,29 +186,6 @@ private static bool AddDependenciesFromCustomAttributeBlob(DependencyList depend return true; } - private static bool AddDependenciesFromField(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string fieldName) - { - FieldDesc field = attributeType.GetField(fieldName); - if (field is not null) - { - if (factory.MetadataManager.IsReflectionBlocked(field)) - return false; - - dependencies.Add(factory.ReflectableField(field), "Custom attribute blob"); - - return true; - } - - // Haven't found it in current type. Check the base type. - TypeDesc baseType = attributeType.BaseType; - - if (baseType != null) - return AddDependenciesFromField(dependencies, factory, baseType, fieldName); - - // Not found. This is bad metadata that will result in a runtime failure, but we shouldn't fail the compilation. - return true; - } - private static bool AddDependenciesFromPropertySetter(DependencyList dependencies, NodeFactory factory, TypeDesc attributeType, string propertyName) { EcmaType attributeTypeDefinition = (EcmaType)attributeType.GetTypeDefinition(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index 54b6424032c5b..0ec69a4f29f76 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -757,29 +757,14 @@ protected virtual ISymbolNode GetBaseTypeNode(NodeFactory factory) return _type.BaseType != null ? factory.NecessaryTypeSymbol(_type.BaseType) : null; } - protected virtual ISymbolNode GetNonNullableValueTypeArrayElementTypeNode(NodeFactory factory) - { - return factory.NecessaryTypeSymbol(((ArrayType)_type).ElementType); - } - private ISymbolNode GetRelatedTypeNode(NodeFactory factory) { ISymbolNode relatedTypeNode = null; - if (_type.IsParameterizedType) + if (_type.IsArray || _type.IsPointer || _type.IsByRef) { var parameterType = ((ParameterizedType)_type).ParameterType; - if (_type.IsArray && parameterType.IsValueType && !parameterType.IsNullable) - { - // This might be a constructed type symbol. There are APIs on Array that allow allocating element - // types through runtime magic ("((Array)new NeverAllocated[1]).GetValue(0)" or IEnumerable) and we don't have - // visibility into that. Conservatively assume element types of constructed arrays are also constructed. - relatedTypeNode = GetNonNullableValueTypeArrayElementTypeNode(factory); - } - else - { - relatedTypeNode = factory.NecessaryTypeSymbol(parameterType); - } + relatedTypeNode = factory.NecessaryTypeSymbol(parameterType); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs index 603f7c7068fdc..8f701ceb236d3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FieldMetadataNode.cs @@ -41,7 +41,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto } protected override string GetName(NodeFactory factory) { - return "Field metadata: " + _field.ToString(); + return "Reflectable field: " + _field.ToString(); } protected override void OnMarked(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs index d4f419c1b424d..0272852f07606 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GCStaticsNode.cs @@ -19,7 +19,6 @@ public class GCStaticsNode : ObjectNode, ISymbolDefinitionNode, ISortableSymbolN public GCStaticsNode(MetadataType type, PreinitializationManager preinitManager) { Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific)); - Debug.Assert(!type.IsGenericDefinition); _type = type; if (preinitManager.IsPreinitialized(type)) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs index 4b821e7865451..a824363f9862f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericDictionaryNode.cs @@ -7,8 +7,6 @@ using Internal.Text; using Internal.TypeSystem; -using CombinedDependencyList = System.Collections.Generic.List.CombinedDependencyListEntry>; - namespace ILCompiler.DependencyAnalysis { /// @@ -198,13 +196,6 @@ public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilde protected override TypeSystemContext Context => _owningMethod.Context; public override TypeSystemEntity OwningEntity => _owningMethod; public MethodDesc OwningMethod => _owningMethod; - public override bool HasConditionalStaticDependencies => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) - { - CombinedDependencyList list = null; - factory.MetadataManager.GetConditionalDependenciesDueToMethodGenericDictionary(ref list, factory, _owningMethod); - return list ?? (IEnumerable)System.Array.Empty(); - } protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs index 427b589090fae..8f1269d8fdfa3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MethodMetadataNode.cs @@ -49,7 +49,7 @@ public override IEnumerable GetStaticDependencies(NodeFacto } protected override string GetName(NodeFactory factory) { - return "Method metadata: " + _method.ToString(); + return "Reflectable method: " + _method.ToString(); } protected override void OnMarked(NodeFactory factory) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index 54efc8c15c026..6597476d51cab 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -294,11 +294,6 @@ private void CreateNodeCaches() return new ReflectableMethodNode(method); }); - _reflectableFields = new NodeCache(field => - { - return new ReflectableFieldNode(field); - }); - _objectGetTypeFlowDependencies = new NodeCache(type => { return new ObjectGetTypeFlowDependenciesNode(type); @@ -857,12 +852,6 @@ public ReflectableMethodNode ReflectableMethod(MethodDesc method) return _reflectableMethods.GetOrAdd(method); } - private NodeCache _reflectableFields; - public ReflectableFieldNode ReflectableField(FieldDesc field) - { - return _reflectableFields.GetOrAdd(field); - } - private NodeCache _objectGetTypeFlowDependencies; internal ObjectGetTypeFlowDependenciesNode ObjectGetTypeFlowDependencies(MetadataType type) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs index 3c06c90b3c144..2e52019a1e153 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NonGCStaticsNode.cs @@ -25,7 +25,6 @@ public class NonGCStaticsNode : ObjectNode, ISymbolDefinitionNode, ISortableSymb public NonGCStaticsNode(MetadataType type, PreinitializationManager preinitializationManager) { Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific)); - Debug.Assert(!type.IsGenericDefinition); _type = type; _preinitializationManager = preinitializationManager; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs index 87ffbb0217d5e..9ec56a6273359 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs @@ -304,8 +304,6 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return comparer.Compare((FieldDesc)_target, (FieldDesc)((ReadyToRunGenericHelperNode)other)._target); case ReadyToRunHelperId.DelegateCtor: return ((DelegateCreationInfo)_target).CompareTo((DelegateCreationInfo)((ReadyToRunGenericHelperNode)other)._target, comparer); - case ReadyToRunHelperId.ConstrainedDirectCall: - return ((ConstrainedCallInfo)_target).CompareTo((ConstrainedCallInfo)((ReadyToRunGenericHelperNode)other)._target, comparer); default: throw new NotImplementedException(); } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectableFieldNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectableFieldNode.cs deleted file mode 100644 index c5bd494505067..0000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectableFieldNode.cs +++ /dev/null @@ -1,105 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; - -using ILCompiler.DependencyAnalysisFramework; - -using Internal.TypeSystem; - -using Debug = System.Diagnostics.Debug; - -namespace ILCompiler.DependencyAnalysis -{ - /// - /// Represents a field that is gettable/settable from reflection. - /// - public class ReflectableFieldNode : DependencyNodeCore - { - private readonly FieldDesc _field; - - public ReflectableFieldNode(FieldDesc field) - { - Debug.Assert(!field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any) - || field.OwningType.ConvertToCanonForm(CanonicalFormKind.Specific) == field.OwningType); - _field = field; - } - - public FieldDesc Field => _field; - - public override IEnumerable GetStaticDependencies(NodeFactory factory) - { - Debug.Assert(!factory.MetadataManager.IsReflectionBlocked(_field.GetTypicalFieldDefinition())); - - DependencyList dependencies = new DependencyList(); - factory.MetadataManager.GetDependenciesDueToReflectability(ref dependencies, factory, _field); - - // No runtime artifacts needed if this is a generic definition or literal field - if (_field.OwningType.IsGenericDefinition || _field.IsLiteral) - { - return dependencies; - } - - FieldDesc typicalField = _field.GetTypicalFieldDefinition(); - if (typicalField != _field) - { - // Ensure we consistently apply reflectability to all fields sharing the same definition. - // Bases for different instantiations of the field have a conditional dependency on the definition node that - // brings a ReflectableField of the instantiated field if it's necessary for it to be reflectable. - dependencies.Add(factory.ReflectableField(typicalField), "Definition of the reflectable field"); - } - - // Runtime reflection stack needs to see the type handle of the owning type - dependencies.Add(factory.MaximallyConstructableType(_field.OwningType), "Instance base of a reflectable field"); - - // Root the static base of the type - if (_field.IsStatic && !_field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) - { - // Infrastructure around static constructors is stashed in the NonGC static base - bool needsNonGcStaticBase = factory.PreinitializationManager.HasLazyStaticConstructor(Field.OwningType); - - if (_field.HasRva) - { - // No reflection access right now - } - else if (_field.IsThreadStatic) - { - dependencies.Add(factory.TypeThreadStaticIndex((MetadataType)_field.OwningType), "Threadstatic base of a reflectable field"); - } - else if (_field.HasGCStaticBase) - { - dependencies.Add(factory.TypeGCStaticsSymbol((MetadataType)_field.OwningType), "GC static base of a reflectable field"); - } - else - { - dependencies.Add(factory.TypeNonGCStaticsSymbol((MetadataType)_field.OwningType), "NonGC static base of a reflectable field"); - needsNonGcStaticBase = false; - } - - if (needsNonGcStaticBase) - { - dependencies.Add(factory.TypeNonGCStaticsSymbol((MetadataType)_field.OwningType), "CCtor context"); - } - } - - // Runtime reflection stack needs to obtain the type handle of the field - // (but there's no type handles for function pointers) - if (!_field.FieldType.IsFunctionPointer) - dependencies.Add(factory.MaximallyConstructableType(_field.FieldType.NormalizeInstantiation()), "Type of the field"); - - return dependencies; - } - protected override string GetName(NodeFactory factory) - { - return "Reflectable field: " + _field.ToString(); - } - - public override bool InterestingForDynamicDependencyAnalysis => false; - public override bool HasDynamicDependencies => false; - public override bool HasConditionalStaticDependencies => false; - public override bool StaticDependenciesAreComputed => true; - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs index 03e318318a7f8..91733ace5276c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ThreadStaticsNode.cs @@ -19,8 +19,7 @@ public class ThreadStaticsNode : EmbeddedObjectNode, ISymbolDefinitionNode public ThreadStaticsNode(MetadataType type, NodeFactory factory) { - Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Specific)); - Debug.Assert(!type.IsGenericDefinition); + Debug.Assert(factory.Target.Abi == TargetAbi.NativeAot || factory.Target.Abi == TargetAbi.CppCodegen); _type = type; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs index b81cddee9188c..e2bff8eb335f2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs @@ -46,14 +46,11 @@ public override IEnumerable GetStaticDependencies(NodeFacto var mdManager = (UsageBasedMetadataManager)factory.MetadataManager; if (_type.IsDelegate) { - // We've decided as a policy that delegate Invoke methods will be generated in full. - // The libraries (e.g. System.Linq.Expressions) have trimming warning suppressions - // in places where they assume IL-level trimming (where the method cannot be removed). - // We ask for a full reflectable method with its method body instead of just the - // metadata. + // A delegate type metadata is rather useless without the Invoke method. + // If someone reflects on a delegate, chances are they're going to look at the signature. var invokeMethod = _type.GetMethod("Invoke", null); if (!mdManager.IsReflectionBlocked(invokeMethod)) - dependencies.Add(factory.ReflectableMethod(invokeMethod), "Delegate invoke method"); + dependencies.Add(factory.MethodMetadata(invokeMethod), "Delegate invoke method metadata"); } if (_type.IsEnum) @@ -61,16 +58,6 @@ public override IEnumerable GetStaticDependencies(NodeFacto // A lot of the enum reflection actually happens on top of the respective MethodTable (e.g. getting the underlying type), // so for enums also include their MethodTable. dependencies.Add(factory.MaximallyConstructableType(_type), "Reflectable enum"); - - // Enums are not useful without their literal fields. The literal fields are not referenced - // from anywhere (source code reference to enums compiles to the underlying numerical constants in IL). - foreach (FieldDesc enumField in _type.GetFields()) - { - if (enumField.IsLiteral) - { - dependencies.Add(factory.FieldMetadata(enumField), "Value of a reflectable enum"); - } - } } // If the user asked for complete metadata to be generated for all types that are getting metadata, ensure that. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExternSymbolMappedField.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExternSymbolMappedField.cs index 8a4bce713efe4..2ee25f4dc7c3b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExternSymbolMappedField.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ExternSymbolMappedField.cs @@ -26,7 +26,6 @@ public ExternSymbolMappedField(TypeDesc fieldType, string symbolName) public override DefType OwningType => _fieldType.Context.SystemModule.GetGlobalModuleType(); public override TypeDesc FieldType => _fieldType; - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() => null; public override bool IsStatic => true; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs index 2efa5cfeb9d1d..20050db2c8cda 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs @@ -8,6 +8,7 @@ using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Xml; + using Internal.IL; using Internal.IL.Stubs; using Internal.TypeSystem; @@ -739,10 +740,172 @@ public AssemblyFeatureInfo(EcmaModule module, IReadOnlyDictionary ms = new UnmanagedMemoryStream(reader.CurrentPointer, length); } - (BodySubstitutions, FieldSubstitutions) = BodySubstitutionsParser.GetSubstitutions(module.Context, ms, resource, module, "name", featureSwitchValues); + (BodySubstitutions, FieldSubstitutions) = SubstitutionsReader.GetSubstitutions(module.Context, XmlReader.Create(ms), module, featureSwitchValues); } } } } + + private class BodySubstitution + { + private object _value; + + private readonly static object Throw = new object(); + + public readonly static BodySubstitution ThrowingBody = new BodySubstitution(Throw); + public readonly static BodySubstitution EmptyBody = new BodySubstitution(null); + + public object Value + { + get + { + Debug.Assert(_value != Throw); + return _value; + } + } + + private BodySubstitution(object value) => _value = value; + + public static BodySubstitution Create(object value) => new BodySubstitution(value); + public MethodIL EmitIL(MethodDesc method) + { + ILEmitter emit = new ILEmitter(); + ILCodeStream codestream = emit.NewCodeStream(); + + if (_value == Throw) + { + codestream.EmitCallThrowHelper(emit, method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowFeatureBodyRemoved")); + } + else if (_value == null) + { + Debug.Assert(method.Signature.ReturnType.IsVoid); + codestream.Emit(ILOpcode.ret); + } + else + { + Debug.Assert(_value is int); + codestream.EmitLdc((int)_value); + codestream.Emit(ILOpcode.ret); + } + + return emit.Link(method); + } + } + + private class SubstitutionsReader : ProcessXmlBase + { + private readonly Dictionary _methodSubstitutions; + private readonly Dictionary _fieldSubstitutions; + + private SubstitutionsReader(TypeSystemContext context, XmlReader reader, ModuleDesc module, IReadOnlyDictionary featureSwitchValues) + : base(context, reader, module, featureSwitchValues) + { + _methodSubstitutions = new Dictionary(); + _fieldSubstitutions = new Dictionary(); + } + + protected override void ProcessMethod(MethodDesc method) + { + string action = GetAttribute("body"); + if (!String.IsNullOrEmpty(action)) + { + switch (action) + { + case "remove": + _methodSubstitutions.Add(method, BodySubstitution.ThrowingBody); + break; + case "stub": + BodySubstitution stubBody; + if (method.Signature.ReturnType.IsVoid) + stubBody = BodySubstitution.EmptyBody; + else + stubBody = BodySubstitution.Create(TryCreateSubstitution(method.Signature.ReturnType, GetAttribute("value"))); + + if (stubBody != null) + { + _methodSubstitutions[method] = stubBody; + } + else + { + // Context.LogWarning ($"Invalid value for '{method.GetDisplayName ()}' stub", 2010, _xmlDocumentLocation); + } + + break; + default: + //Context.LogWarning($"Unknown body modification '{action}' for '{method.GetDisplayName()}'", 2011, _xmlDocumentLocation); + break; + } + } + } + + protected override void ProcessField(FieldDesc field) + { + if (!field.IsStatic || field.IsLiteral) + { + // Context.LogWarning ($"Substituted field '{field.GetDisplayName ()}' needs to be static field.", 2013, _xmlDocumentLocation); + return; + } + + string value = GetAttribute("value"); + if (string.IsNullOrEmpty(value)) + { + //Context.LogWarning($"Missing 'value' attribute for field '{field.GetDisplayName()}'.", 2014, _xmlDocumentLocation); + return; + } + + object substitution = TryCreateSubstitution(field.FieldType, value); + if (substitution == null) + { + //Context.LogWarning($"Invalid value '{value}' for '{field.GetDisplayName()}'.", 2015, _xmlDocumentLocation); + return; + } + + if (String.Equals(GetAttribute("initialize"), "true", StringComparison.InvariantCultureIgnoreCase)) + { + // We would need to also mess with the cctor of the type to set the field to this value: + // + // * Linker will remove all stsfld instructions referencing this field from the cctor + // * It will place an explicit stsfld in front of the last "ret" instruction in the cctor + // + // This approach... has issues. + throw new NotSupportedException(); + } + + _fieldSubstitutions[field] = substitution; + } + + private object TryCreateSubstitution(TypeDesc type, string value) + { + switch (type.UnderlyingType.Category) + { + case TypeFlags.Int32: + if (string.IsNullOrEmpty(value)) + return 0; + else if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int iresult)) + return iresult; + break; + + case TypeFlags.Boolean: + if (String.IsNullOrEmpty(value)) + return 0; + else if (bool.TryParse(value, out bool bvalue)) + return bvalue ? 1 : 0; + else + goto case TypeFlags.Int32; + + default: + throw new NotSupportedException(type.ToString()); + } + + return null; + } + + public static (Dictionary, Dictionary) GetSubstitutions(TypeSystemContext context, XmlReader reader, ModuleDesc module, IReadOnlyDictionary featureSwitchValues) + { + var rdr = new SubstitutionsReader(context, reader, module, featureSwitchValues); + rdr.ProcessXml(); + return (rdr._methodSubstitutions, rdr._fieldSubstitutions); + } + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/IRootingServiceProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/IRootingServiceProvider.cs index c368c762e64ca..adff5b36116e1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/IRootingServiceProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/IRootingServiceProvider.cs @@ -13,7 +13,6 @@ public interface IRootingServiceProvider void AddCompilationRoot(MethodDesc method, string reason, string exportName = null); void AddCompilationRoot(TypeDesc type, string reason); void AddReflectionRoot(MethodDesc method, string reason); - void AddReflectionRoot(FieldDesc field, string reason); void RootThreadStaticBaseForType(TypeDesc type, string reason); void RootGCStaticBaseForType(TypeDesc type, string reason); void RootNonGCStaticBaseForType(TypeDesc type, string reason); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/GraphBuilder.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/GraphBuilder.cs index fd03cb6595787..5cdf10665fa28 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/GraphBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/LazyGenerics/GraphBuilder.cs @@ -201,11 +201,8 @@ private void WalkMethod(EcmaMethod method) && _metadataReader.GetMemberReference((MemberReferenceHandle)accessedMethod).Parent.Kind == HandleKind.TypeSpecification)) { var m = methodIL.GetObject(MetadataTokens.GetToken(accessedMethod), NotFoundBehavior.ReturnNull) as MethodDesc; - if (m != null) - { - ProcessTypeReference(m.OwningType, typeContext, methodContext); - ProcessMethodCall(m, typeContext, methodContext); - } + ProcessTypeReference(m.OwningType, typeContext, methodContext); + ProcessMethodCall(m, typeContext, methodContext); } break; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 489a13ac271f8..5ebf7f1ed3a24 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -221,9 +221,6 @@ protected virtual void Graph_NewMarkedNode(DependencyNodeCore obj) if (dictionaryNode != null) { _genericDictionariesGenerated.Add(dictionaryNode); - - if (dictionaryNode.OwningEntity is MethodDesc method && AllMethodsCanBeReflectable) - _reflectableMethods.Add(method); } if (obj is StructMarshallingDataNode structMarshallingDataNode) @@ -348,19 +345,6 @@ public void GetDependenciesDueToReflectability(ref DependencyList dependencies, } } - /// - /// This method is an extension point that can provide additional metadata-based dependencies to generated fields. - /// - public void GetDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) - { - MetadataCategory category = GetMetadataCategory(field); - - if ((category & MetadataCategory.Description) != 0) - { - GetMetadataDependenciesDueToReflectability(ref dependencies, factory, field); - } - } - /// /// This method is an extension point that can provide additional metadata-based dependencies on a virtual method. /// @@ -375,13 +359,6 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency // and property setters) } - protected virtual void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) - { - // MetadataManagers can override this to provide additional dependencies caused by the emission of metadata - // (E.g. dependencies caused by the field having custom attributes applied to it: making sure we compile the attribute constructor - // and property setters) - } - /// /// This method is an extension point that can provide additional metadata-based dependencies to generated EETypes. /// @@ -394,6 +371,15 @@ public void GetDependenciesDueToReflectability(ref DependencyList dependencies, GetMetadataDependenciesDueToReflectability(ref dependencies, factory, type); } + if ((category & MetadataCategory.RuntimeMapping) != 0) + { + // We're going to generate a mapping table entry for this. Collect dependencies. + + // Nothing special is needed for the mapping table (we only emit the MethodTable and we already + // have one, since we got this callback). But check if a child wants to do something extra. + GetRuntimeMappingDependenciesDueToReflectability(ref dependencies, factory, type); + } + GetDependenciesDueToEETypePresence(ref dependencies, factory, type); } @@ -404,6 +390,12 @@ protected virtual void GetMetadataDependenciesDueToReflectability(ref Dependency // and property setters) } + protected virtual void GetRuntimeMappingDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) + { + // MetadataManagers can override this to provide additional dependencies caused by the emission of a runtime + // mapping for a type. + } + protected virtual void GetDependenciesDueToEETypePresence(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { // MetadataManagers can override this to provide additional dependencies caused by the emission of an MethodTable. @@ -468,12 +460,6 @@ public void GetDependenciesDueToMethodCodePresence(ref DependencyList dependenci GetDependenciesDueToMethodCodePresenceInternal(ref dependencies, factory, method, methodIL); } - public virtual void GetConditionalDependenciesDueToMethodGenericDictionary(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) - { - // MetadataManagers can override this to provide additional dependencies caused by the presence of - // method generic dictionary. - } - public virtual void GetConditionalDependenciesDueToMethodCodePresence(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) { // MetadataManagers can override this to provide additional dependencies caused by the presence of diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs index 062c80897e95f..e4c06223c6c40 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ProcessLinkerXmlBase.cs @@ -50,7 +50,7 @@ public abstract class ProcessLinkerXmlBase private readonly IReadOnlyDictionary _featureSwitchValues; protected readonly TypeSystemContext _context; - protected ProcessLinkerXmlBase(TypeSystemContext context, Stream documentStream, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) + protected ProcessLinkerXmlBase(TypeSystemContext context, UnmanagedMemoryStream documentStream, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) { _context = context; using (documentStream) @@ -61,7 +61,7 @@ protected ProcessLinkerXmlBase(TypeSystemContext context, Stream documentStream, _featureSwitchValues = featureSwitchValues; } - protected ProcessLinkerXmlBase(TypeSystemContext context, Stream documentStream, ManifestResource resource, ModuleDesc resourceAssembly, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) + protected ProcessLinkerXmlBase(TypeSystemContext context, UnmanagedMemoryStream documentStream, ManifestResource resource, ModuleDesc resourceAssembly, string xmlDocumentLocation, IReadOnlyDictionary featureSwitchValues) : this(context, documentStream, xmlDocumentLocation, featureSwitchValues) { _owningModule = resourceAssembly ?? throw new ArgumentNullException(nameof(resourceAssembly)); @@ -489,31 +489,6 @@ protected static string GetAttribute(XPathNavigator nav, string attribute) return nav.GetAttribute(attribute, XmlNamespace); } - public static string GetMethodSignature(MethodDesc meth, bool includeGenericParameters) - { - StringBuilder sb = new StringBuilder(); - CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature.ReturnType); - sb.Append(' '); - sb.Append(meth.Name); - if (includeGenericParameters && meth.HasInstantiation) - { - sb.Append('`'); - sb.Append(meth.Instantiation.Length); - } - - sb.Append('('); - for (int i = 0; i < meth.Signature.Length; i++) - { - if (i > 0) - sb.Append(','); - - CecilTypeNameFormatter.Instance.AppendName(sb, meth.Signature[i]); - } - - sb.Append(')'); - return sb.ToString(); - } - #if false protected MessageOrigin GetMessageOriginForPosition(XPathNavigator position) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs index 987e31fc03c27..cd9cdcf8f7039 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingHelpers.cs @@ -90,11 +90,6 @@ public static void RootType(IRootingServiceProvider rootProvider, TypeDesc type, TryRootMethod(rootProvider, method, reason); } } - - foreach (FieldDesc field in type.GetFields()) - { - TryRootField(rootProvider, field, reason); - } } } @@ -119,38 +114,6 @@ public static void RootMethod(IRootingServiceProvider rootProvider, MethodDesc m rootProvider.AddReflectionRoot(method, reason); } - public static bool TryRootField(IRootingServiceProvider rootProvider, FieldDesc field, string reason) - { - try - { - RootField(rootProvider, field, reason); - return true; - } - catch (TypeSystemException) - { - return false; - } - } - - public static void RootField(IRootingServiceProvider rootProvider, FieldDesc field, string reason) - { - // Make sure we're not putting something into the graph that will crash later. - if (field.IsLiteral) - { - // Nothing to check - } - else if (field.IsStatic) - { - field.OwningType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizes); - } - else - { - field.OwningType.ComputeInstanceLayout(InstanceLayoutKind.TypeOnly); - } - - rootProvider.AddReflectionRoot(field, reason); - } - public static bool TryGetDependenciesForReflectedMethod(ref DependencyList dependencies, NodeFactory factory, MethodDesc method, string reason) { MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); @@ -175,7 +138,7 @@ public static bool TryGetDependenciesForReflectedMethod(ref DependencyList depen if (method.OwningType.IsGenericDefinition || method.OwningType.ContainsSignatureVariables(treatGenericParameterLikeSignatureVariable: true)) { TypeDesc owningType = method.OwningType.GetTypeDefinition(); - Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(owningType.Instantiation, allowCanon: !method.HasInstantiation); + Instantiation inst = TypeExtensions.GetInstantiationThatMeetsConstraints(owningType.Instantiation, allowCanon: false); if (inst.IsNull) { return false; @@ -217,22 +180,6 @@ public static bool TryGetDependenciesForReflectedMethod(ref DependencyList depen public static bool TryGetDependenciesForReflectedField(ref DependencyList dependencies, NodeFactory factory, FieldDesc field, string reason) { - FieldDesc typicalField = field.GetTypicalFieldDefinition(); - if (factory.MetadataManager.IsReflectionBlocked(typicalField)) - { - return false; - } - - dependencies ??= new DependencyList(); - - // If this is a field on generic type, make sure we at minimum have the metadata - // for it. This hedges against the risk that we fail to figure out an instantiated base - // for it below. - if (typicalField.OwningType.HasInstantiation) - { - dependencies.Add(factory.ReflectableField(typicalField), reason); - } - // If there's any genericness involved, try to create a fitting instantiation that would be usable at runtime. // This is not a complete solution to the problem. // If we ever decide that MakeGenericType/MakeGenericMethod should simply be considered unsafe, this code can be deleted @@ -251,7 +198,45 @@ public static bool TryGetDependenciesForReflectedField(ref DependencyList depend ((MetadataType)owningType).MakeInstantiatedType(inst)); } - dependencies.Add(factory.ReflectableField(field), reason); + if (factory.MetadataManager.IsReflectionBlocked(field)) + { + return false; + } + + if (!TryGetDependenciesForReflectedType(ref dependencies, factory, field.OwningType, reason)) + { + return false; + } + + // Currently generating the base of the type is enough to make the field reflectable. + + if (field.OwningType.IsCanonicalSubtype(CanonicalFormKind.Any)) + { + return true; + } + + if (field.IsStatic && !field.IsLiteral && !field.HasRva) + { + bool cctorContextAdded = false; + if (field.IsThreadStatic) + { + dependencies.Add(factory.TypeThreadStaticIndex((MetadataType)field.OwningType), reason); + } + else if (field.HasGCStaticBase) + { + dependencies.Add(factory.TypeGCStaticsSymbol((MetadataType)field.OwningType), reason); + } + else + { + dependencies.Add(factory.TypeNonGCStaticsSymbol((MetadataType)field.OwningType), reason); + cctorContextAdded = true; + } + + if (!cctorContextAdded && factory.PreinitializationManager.HasLazyStaticConstructor(field.OwningType)) + { + dependencies.Add(factory.TypeNonGCStaticsSymbol((MetadataType)field.OwningType), reason); + } + } return true; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingServiceProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingServiceProvider.cs index 31419393a1d84..ce5dd8f931f91 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingServiceProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RootingServiceProvider.cs @@ -46,12 +46,6 @@ public void AddReflectionRoot(MethodDesc method, string reason) _rootAdder(_factory.ReflectableMethod(method), reason); } - public void AddReflectionRoot(FieldDesc field, string reason) - { - if (!_factory.MetadataManager.IsReflectionBlocked(field)) - _rootAdder(_factory.ReflectableField(field), reason); - } - public void RootThreadStaticBaseForType(TypeDesc type, string reason) { Debug.Assert(!type.IsGenericDefinition); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs index 77af00708d864..c5b5a458afbd3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs @@ -40,6 +40,7 @@ public sealed class UsageBasedMetadataManager : GeneratingMetadataManager private readonly CompilationModuleGroup _compilationModuleGroup; internal readonly UsageBasedMetadataGenerationOptions _generationOptions; + private readonly bool _hasPreciseFieldUsageInformation; private readonly FeatureSwitchHashtable _featureSwitchHashtable; @@ -47,7 +48,6 @@ public sealed class UsageBasedMetadataManager : GeneratingMetadataManager private readonly List _fieldsWithMetadata = new List(); private readonly List _methodsWithMetadata = new List(); private readonly List _typesWithMetadata = new List(); - private readonly List _fieldsWithRuntimeMapping = new List(); private readonly List _customAttributesWithMetadata = new List(); private readonly HashSet _rootEntireAssembliesExaminedModules = new HashSet(); @@ -75,6 +75,8 @@ public sealed class UsageBasedMetadataManager : GeneratingMetadataManager IEnumerable trimmedAssemblies) : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy, invokeThunkGenerationPolicy) { + // We use this to mark places that would behave differently if we tracked exact fields used. + _hasPreciseFieldUsageInformation = false; _compilationModuleGroup = group; _generationOptions = generationOptions; @@ -120,22 +122,6 @@ protected override void Graph_NewMarkedNode(DependencyNodeCore obj) { _customAttributesWithMetadata.Add(customAttributeMetadataNode.CustomAttribute); } - - var reflectableFieldNode = obj as ReflectableFieldNode; - if (reflectableFieldNode != null) - { - FieldDesc field = reflectableFieldNode.Field; - TypeDesc fieldOwningType = field.OwningType; - - // Filter out to those that make sense to have in the mapping tables - if (!fieldOwningType.IsGenericDefinition - && !field.IsLiteral - && (!fieldOwningType.IsCanonicalSubtype(CanonicalFormKind.Specific) || !field.IsStatic)) - { - Debug.Assert((GetMetadataCategory(field) & MetadataCategory.RuntimeMapping) != 0); - _fieldsWithRuntimeMapping.Add(field); - } - } } protected override MetadataCategory GetMetadataCategory(FieldDesc field) @@ -187,7 +173,7 @@ protected override MetadataCategory GetMetadataCategory(TypeDesc type) return category; } - protected override bool AllMethodsCanBeReflectable => (_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0; + protected override bool AllMethodsCanBeReflectable => (_generationOptions & UsageBasedMetadataGenerationOptions.ReflectedMembersOnly) == 0; protected override void ComputeMetadata(NodeFactory factory, out byte[] metadataBlob, @@ -206,16 +192,26 @@ protected override void GetMetadataDependenciesDueToReflectability(ref Dependenc dependencies.Add(factory.MethodMetadata(method.GetTypicalMethodDefinition()), "Reflectable method"); } - protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) - { - dependencies = dependencies ?? new DependencyList(); - dependencies.Add(factory.FieldMetadata(field.GetTypicalFieldDefinition()), "Reflectable field"); - } - protected override void GetMetadataDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { TypeMetadataNode.GetMetadataDependencies(ref dependencies, factory, type, "Reflectable type"); + // If we don't have precise field usage information, apply policy that all fields that + // are eligible to have metadata get metadata. + if (!_hasPreciseFieldUsageInformation) + { + TypeDesc typeDefinition = type.GetTypeDefinition(); + + foreach (FieldDesc field in typeDefinition.GetFields()) + { + if ((GetMetadataCategory(field) & MetadataCategory.Description) != 0) + { + dependencies = dependencies ?? new DependencyList(); + dependencies.Add(factory.FieldMetadata(field), "Field of a reflectable type"); + } + } + } + MetadataType mdType = type as MetadataType; // If anonymous type heuristic is turned on and this is an anonymous type, make sure we have @@ -342,19 +338,48 @@ private static bool IsTrimmableAssembly(ModuleDesc assembly) return false; } - public override bool HasConditionalDependenciesDueToEETypePresence(TypeDesc type) + protected override void GetRuntimeMappingDependenciesDueToReflectability(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) { - // Note: these are duplicated with the checks in GetConditionalDependenciesDueToEETypePresence + // If we precisely track field usage, we don't need the logic below. + if (_hasPreciseFieldUsageInformation) + return; + + const string reason = "Reflection"; + + // This logic is applying policy: if a type is reflectable (has a runtime mapping), all of it's fields + // are reflectable (with a runtime mapping) as well. + // This is potentially overly broad (we don't know if any of the fields will actually be eligile + // for metadata - e.g. they could all be reflection blocked). This is fine since lack of + // precise field usage information is already not ideal from a size on disk perspective. + // The more precise way to do this would be to go over each field, check that it's eligible for RuntimeMapping + // according to the policy (e.g. it's not blocked), and only then root the base of the field. + if (type is MetadataType metadataType && !type.IsGenericDefinition) + { + Debug.Assert(!type.IsCanonicalSubtype(CanonicalFormKind.Any)); - // If there's dataflow annotations on the type, we have conditional dependencies - if (type.IsDefType && !type.IsInterface && FlowAnnotations.GetTypeAnnotation(type) != default) - return true; + if (metadataType.GCStaticFieldSize.AsInt > 0) + { + dependencies.Add(factory.TypeGCStaticsSymbol(metadataType), reason); + } - // If we need to ensure fields are consistently reflectable on various generic instances - if (type.HasInstantiation && !type.IsGenericDefinition && !IsReflectionBlocked(type)) - return true; + if (metadataType.NonGCStaticFieldSize.AsInt > 0 || factory.PreinitializationManager.HasLazyStaticConstructor(metadataType)) + { + dependencies.Add(factory.TypeNonGCStaticsSymbol(metadataType), reason); + } - return false; + if (metadataType.ThreadGcStaticFieldSize.AsInt > 0) + { + dependencies.Add(factory.TypeThreadStaticIndex(metadataType), reason); + } + + Debug.Assert(metadataType.ThreadNonGcStaticFieldSize.AsInt == 0); + } + } + + public override bool HasConditionalDependenciesDueToEETypePresence(TypeDesc type) + { + // Note: duplicated with the check in GetConditionalDependenciesDueToEETypePresence + return type.IsDefType && !type.IsInterface && FlowAnnotations.GetTypeAnnotation(type) != default; } public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedDependencyList dependencies, NodeFactory factory, TypeDesc type) @@ -410,34 +435,16 @@ public override void GetConditionalDependenciesDueToEETypePresence(ref CombinedD // of the bases/interfaces are annotated. // ObjectGetTypeFlowDependencies don't need to be conditional in that case. They'll be added as needed. } - - // Ensure fields can be consistently reflection set & get. - if (type.HasInstantiation && !type.IsTypeDefinition && !IsReflectionBlocked(type)) - { - foreach (FieldDesc field in type.GetFields()) - { - // Tiny optimization: no get/set for literal fields since they only exist in metadata - if (field.IsLiteral) - continue; - - if (IsReflectionBlocked(field)) - continue; - - dependencies ??= new CombinedDependencyList(); - dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( - factory.ReflectableField(field), - factory.ReflectableField(field.GetTypicalFieldDefinition()), - "GetType called on the interface")); - } - } } public override void GetDependenciesDueToLdToken(ref DependencyList dependencies, NodeFactory factory, FieldDesc field) { - if (!IsReflectionBlocked(field)) + // In order for the RuntimeFieldHandle data structure to be usable at runtime, ensure the field + // is generating metadata. + if ((GetMetadataCategory(field) & MetadataCategory.Description) == MetadataCategory.Description) { dependencies = dependencies ?? new DependencyList(); - dependencies.Add(factory.ReflectableField(field), "LDTOKEN field"); + dependencies.Add(factory.FieldMetadata(field.GetTypicalFieldDefinition()), "LDTOKEN field"); } } @@ -527,38 +534,18 @@ protected override void GetDependenciesDueToMethodCodePresenceInternal(ref Depen } // Presence of code might trigger the reflectability dependencies. - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) + if ((_generationOptions & UsageBasedMetadataGenerationOptions.ReflectedMembersOnly) == 0) { GetDependenciesDueToReflectability(ref dependencies, factory, method); } } - public override void GetConditionalDependenciesDueToMethodGenericDictionary(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) - { - Debug.Assert(!method.IsSharedByGenericInstantiations && method.HasInstantiation && method.GetCanonMethodTarget(CanonicalFormKind.Specific) != method); - - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) == 0 - && !IsReflectionBlocked(method)) - { - // Ensure that if SomeMethod is considered reflectable, SomeMethod is also reflectable. - // We only need this because there's a file format limitation in the reflection mapping tables that - // requires generic methods to be concrete (i.e. SomeMethod<__Canon> can never be in the mapping table). - // If we ever lift this limitation, this code can be deleted: the reflectability is going to be covered - // by GetConditionalDependenciesDueToMethodCodePresence below (we get that callback for SomeMethod<__Canon>). - MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); - - dependencies ??= new CombinedDependencyList(); - dependencies.Add(new DependencyNodeCore.CombinedDependencyListEntry( - factory.ReflectableMethod(method), factory.ReflectableMethod(typicalMethod), "Reflectability of methods is same across genericness")); - } - } - public override void GetConditionalDependenciesDueToMethodCodePresence(ref CombinedDependencyList dependencies, NodeFactory factory, MethodDesc method) { MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); // Ensure methods with genericness have the same reflectability by injecting a conditional dependency. - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) == 0 + if ((_generationOptions & UsageBasedMetadataGenerationOptions.ReflectedMembersOnly) != 0 && method != typicalMethod) { dependencies ??= new CombinedDependencyList(); @@ -569,7 +556,7 @@ public override void GetConditionalDependenciesDueToMethodCodePresence(ref Combi public override void GetDependenciesDueToVirtualMethodReflectability(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) { - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) + if ((_generationOptions & UsageBasedMetadataGenerationOptions.ReflectedMembersOnly) == 0) { // If we have a use of an abstract method, GetDependenciesDueToReflectability is not going to see the method // as being used since there's no body. We inject a dependency on a new node that serves as a logical method body @@ -584,7 +571,26 @@ public override void GetDependenciesDueToVirtualMethodReflectability(ref Depende protected override IEnumerable GetFieldsWithRuntimeMapping() { - return _fieldsWithRuntimeMapping; + if (_hasPreciseFieldUsageInformation) + { + // TODO + } + else + { + // This applies a policy that fields inherit runtime mapping from their owning type, + // unless they are blocked. + foreach (var type in GetTypesWithRuntimeMapping()) + { + if (type.IsGenericDefinition) + continue; + + foreach (var field in type.GetFields()) + { + if ((GetMetadataCategory(field) & MetadataCategory.RuntimeMapping) != 0) + yield return field; + } + } + } } public override IEnumerable GetCompilationModulesWithMetadata() @@ -619,60 +625,6 @@ public override void GetDependenciesDueToAccess(ref DependencyList dependencies, dependencies = dependencies ?? new DependencyList(); dependencies.Add(factory.DataflowAnalyzedMethod(methodIL.GetMethodILDefinition()), "Access to interesting field"); } - - string reason = "Use of a field"; - - bool generatesMetadata = false; - if (!IsReflectionBlocked(writtenField)) - { - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) - { - // If access to the field should trigger metadata generation, we should generate the field - generatesMetadata = true; - } - else - { - // There's an invalid suppression in the CoreLib that assumes used fields on attributes will be kept. - // It's used in the reflection-based implementation of Attribute.Equals and Attribute.GetHashCode. - // .NET Native used to have a non-reflection based implementation of Equals/GetHashCode to get around - // this problem. We could explore that as well, but for now, emulate the fact that accessed fields - // on custom attributes will be visible in reflection metadata. - MetadataType currentType = (MetadataType)writtenField.OwningType.BaseType; - while (currentType != null) - { - if (currentType.Module == factory.TypeSystemContext.SystemModule - && currentType.Name == "Attribute" && currentType.Namespace == "System") - { - generatesMetadata = true; - reason = "Field of an attribute"; - break; - } - - currentType = currentType.MetadataBaseType; - } - } - } - - if (generatesMetadata) - { - FieldDesc fieldToReport = writtenField; - - // The field could be on something odd like Foo<__Canon, object>. Normalize to Foo<__Canon, __Canon>. - TypeDesc fieldOwningType = writtenField.OwningType; - if (fieldOwningType.IsCanonicalSubtype(CanonicalFormKind.Specific)) - { - TypeDesc fieldOwningTypeNormalized = fieldOwningType.NormalizeInstantiation(); - if (fieldOwningType != fieldOwningTypeNormalized) - { - fieldToReport = factory.TypeSystemContext.GetFieldForInstantiatedType( - writtenField.GetTypicalFieldDefinition(), - (InstantiatedType)fieldOwningTypeNormalized); - } - } - - dependencies = dependencies ?? new DependencyList(); - dependencies.Add(factory.ReflectableField(fieldToReport), reason); - } } public override void GetDependenciesDueToAccess(ref DependencyList dependencies, NodeFactory factory, MethodIL methodIL, MethodDesc calledMethod) @@ -703,21 +655,13 @@ private void GetFlowDependenciesForInstantiation(ref DependencyList dependencies var genericParameter = (GenericParameterDesc)typicalInstantiation[i]; if (FlowAnnotations.GetGenericParameterAnnotation(genericParameter) != default) { - try - { - var deps = ILCompiler.Dataflow.ReflectionMethodBodyScanner.ProcessGenericArgumentDataFlow(factory, FlowAnnotations, Logger, genericParameter, instantiation[i], source); - if (deps.Count > 0) - { - if (dependencies == null) - dependencies = deps; - else - dependencies.AddRange(deps); - } - } - catch (TypeSystemException) + var deps = ILCompiler.Dataflow.ReflectionMethodBodyScanner.ProcessGenericArgumentDataFlow(factory, FlowAnnotations, Logger, genericParameter, instantiation[i], source); + if (deps.Count > 0) { - // Wasn't able to do dataflow because of missing references or something like that. - // This likely won't compile either, so we don't care about missing dependencies. + if (dependencies == null) + dependencies = deps; + else + dependencies.AddRange(deps); } } } @@ -741,12 +685,6 @@ public override void GetDependenciesForGenericDictionary(ref DependencyList depe GetFlowDependenciesForInstantiation(ref dependencies, factory, owningType.Instantiation, owningType.GetTypeDefinition().Instantiation, method); } } - - // Presence of code might trigger the reflectability dependencies. - if ((_generationOptions & UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts) != 0) - { - GetDependenciesDueToReflectability(ref dependencies, factory, method); - } } public override void GetDependenciesForGenericDictionary(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) @@ -857,16 +795,41 @@ public MetadataManager ToAnalysisBasedMetadataManager() reflectableFields[fieldWithMetadata] = MetadataCategory.Description; } - foreach (var fieldWithRuntimeMapping in _fieldsWithRuntimeMapping) + if (_hasPreciseFieldUsageInformation) { - reflectableFields[fieldWithRuntimeMapping] |= MetadataCategory.RuntimeMapping; - - // Also set the description bit if the definition is getting metadata. - FieldDesc typicalField = fieldWithRuntimeMapping.GetTypicalFieldDefinition(); - if (fieldWithRuntimeMapping != typicalField && - (reflectableFields[typicalField] & MetadataCategory.Description) != 0) + // TODO + } + else + { + // If we don't have precise field usage information we apply a policy that + // says the fields inherit the setting from the type, potentially restricted by blocking. + // (I.e. if a type has RuntimeMapping metadata, the field has RuntimeMapping too, unless blocked.) + foreach (var reflectableType in reflectableTypes.ToEnumerable()) { - reflectableFields[fieldWithRuntimeMapping] |= MetadataCategory.Description; + if (reflectableType.Entity.IsGenericDefinition) + continue; + + if (reflectableType.Entity.IsCanonicalSubtype(CanonicalFormKind.Specific)) + continue; + + if ((reflectableType.Category & MetadataCategory.RuntimeMapping) == 0) + continue; + + foreach (var field in reflectableType.Entity.GetFields()) + { + if (!IsReflectionBlocked(field)) + { + reflectableFields[field] |= MetadataCategory.RuntimeMapping; + + // Also set the description bit if the definition is getting metadata. + FieldDesc typicalField = field.GetTypicalFieldDefinition(); + if (field != typicalField && + (reflectableFields[typicalField] & MetadataCategory.Description) != 0) + { + reflectableFields[field] |= MetadataCategory.Description; + } + } + } } } @@ -1105,9 +1068,9 @@ public enum UsageBasedMetadataGenerationOptions ReflectionILScanning = 4, /// - /// Consider all native artifacts (native method bodies, etc) visible from reflection. + /// Only members that were seen as reflected on will be reflectable. /// - CreateReflectableArtifacts = 8, + ReflectedMembersOnly = 8, /// /// Fully root used assemblies that are not marked IsTrimmable in metadata. diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index 0f4dded3fe585..20246847b661c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -264,8 +264,6 @@ private void ImportCall(ILOpcode opcode, int token) var method = (MethodDesc)_canonMethodIL.GetObject(token); _compilation.TypeSystemContext.EnsureLoadableMethod(method); - if ((method.Signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask) == MethodSignatureFlags.CallingConventionVarargs) - ThrowHelper.ThrowBadImageFormatException(); _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _compilation.NodeFactory, _canonMethodIL, method); @@ -977,9 +975,8 @@ private void ImportReadOnlyPrefix() private void ImportFieldAccess(int token, bool isStatic, string reason) { var field = (FieldDesc)_methodIL.GetObject(token); - var canonField = (FieldDesc)_canonMethodIL.GetObject(token); - _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _compilation.NodeFactory, _canonMethodIL, canonField); + _compilation.NodeFactory.MetadataManager.GetDependenciesDueToAccess(ref _dependencies, _compilation.NodeFactory, _canonMethodIL, field); // Covers both ldsfld/ldsflda and ldfld/ldflda with a static field if (isStatic || field.IsStatic) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 12fadf2a915f3..6f19f9f7acc73 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -300,8 +300,6 @@ - - @@ -353,7 +351,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs index 62bdb023525e6..be0d8af909f72 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs @@ -218,12 +218,7 @@ private void WritePDBDataHelper(string dllPath, IEnumerable methods) const int capacity = 1024; var pdbFilePathBuilder = new char[capacity]; _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(capacity - 1) /* remove 1 byte for null */); - int length = 0; - while (length < pdbFilePathBuilder.Length && pdbFilePathBuilder[length] != '\0') - { - length++; - } - _pdbFilePath = new string(pdbFilePathBuilder, 0, length); + _pdbFilePath = pdbFilePathBuilder.ToString(); } _ngenWriter.OpenModW(originalDllPath, Path.GetFileName(originalDllPath), out _pdbMod); diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs index 619f319888fc9..8a1166f43a39b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/SymNgenWriterWrapper.cs @@ -21,7 +21,6 @@ private SymNgenWriterWrapper(IntPtr writer2Inst) { var iid = ISymNGenWriter2.IID; int hr = Marshal.QueryInterface(ptr, ref iid, out IntPtr ngenWriterInst); - Marshal.Release(ptr); if (hr != 0) { return null; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index 44925d84cfe21..550b4e451adc0 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -663,7 +663,7 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase graph) if (inputModule == TypeSystemContext.SystemModule) { AttributePresenceFilterNode attributePresenceTable = new AttributePresenceFilterNode(inputModule); - tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.AttributePresence, attributePresenceTable, attributePresenceTable); + Header.Add(Internal.Runtime.ReadyToRunSectionType.AttributePresence, attributePresenceTable, attributePresenceTable); } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 6e62f81bdbf34..2e7452815e652 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -361,9 +361,8 @@ unsafe partial class CorInfoImpl private MethodWithGCInfo _methodCodeNode; private OffsetMapping[] _debugLocInfos; private NativeVarInfo[] _debugVarInfos; - private HashSet _inlinedMethods; + private ArrayBuilder _inlinedMethods; private UnboxingMethodDescFactory _unboxingThunkFactory = new UnboxingMethodDescFactory(); - private List _precodeFixups; public CorInfoImpl(ReadyToRunCodegenCompilation compilation) : this() @@ -371,12 +370,6 @@ public CorInfoImpl(ReadyToRunCodegenCompilation compilation) _compilation = compilation; } - private void AddPrecodeFixup(ISymbolNode node) - { - _precodeFixups = _precodeFixups ?? new List(); - _precodeFixups.Add(node); - } - private static mdToken FindGenericMethodArgTypeSpec(EcmaModule module) { // Find the TypeSpec for "!!0" @@ -1334,7 +1327,7 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout && (fieldOffset <= FieldFixupSignature.MaxCheckableOffset)) { // ENCODE_CHECK_FIELD_OFFSET - AddPrecodeFixup(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); + _methodCodeNode.Fixups.Add(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); } } else @@ -1388,7 +1381,7 @@ private void getFieldInfo(ref CORINFO_RESOLVED_TOKEN pResolvedToken, CORINFO_MET if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout && (fieldOffset <= FieldFixupSignature.MaxCheckableOffset)) { // ENCODE_CHECK_FIELD_OFFSET - AddPrecodeFixup(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); + _methodCodeNode.Fixups.Add(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); } pResult->fieldLookup = CreateConstLookupToSymbol( @@ -1850,7 +1843,7 @@ private void classMustBeLoadedBeforeCodeIsRun(TypeDesc type) if (!type.IsPrimitive) { ISymbolNode node = _compilation.SymbolNodeFactory.CreateReadyToRunHelper(ReadyToRunHelperId.TypeHandle, type); - AddPrecodeFixup(node); + _methodCodeNode.Fixups.Add(node); } } @@ -2372,7 +2365,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult, if (pResult->offset > FieldFixupSignature.MaxCheckableOffset) throw new RequiresRuntimeJitException(callerMethod.ToString() + " -> " + field.ToString()); - AddPrecodeFixup(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); + _methodCodeNode.Fixups.Add(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); // No-op other than generating the check field offset fixup } else @@ -2390,7 +2383,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult, if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout && !callerMethod.IsNonVersionable() && (pResult->offset <= FieldFixupSignature.MaxCheckableOffset)) { // ENCODE_CHECK_FIELD_OFFSET - AddPrecodeFixup(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); + _methodCodeNode.Fixups.Add(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); } // ENCODE_NONE } @@ -2399,7 +2392,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult, if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout && !callerMethod.IsNonVersionable() && (pResult->offset <= FieldFixupSignature.MaxCheckableOffset)) { // ENCODE_CHECK_FIELD_OFFSET - AddPrecodeFixup(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); + _methodCodeNode.Fixups.Add(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); } // ENCODE_NONE } @@ -2410,7 +2403,7 @@ private void EncodeFieldBaseOffset(FieldDesc field, CORINFO_FIELD_INFO* pResult, if (_compilation.SymbolNodeFactory.VerifyTypeAndFieldLayout && !callerMethod.IsNonVersionable() && (pResult->offset <= FieldFixupSignature.MaxCheckableOffset)) { // ENCODE_CHECK_FIELD_OFFSET - AddPrecodeFixup(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); + _methodCodeNode.Fixups.Add(_compilation.SymbolNodeFactory.CheckFieldOffset(field)); } // ENCODE_FIELD_BASE_OFFSET @@ -2643,56 +2636,14 @@ private void setEHinfo(uint EHnumber, ref CORINFO_EH_CLAUSE clause) _ehClauses[EHnumber] = clause; } - private readonly Stack> _stashedPrecodeFixups = new Stack>(); - private readonly Stack> _stashedInlinedMethods = new Stack>(); - - private void beginInlining(CORINFO_METHOD_STRUCT_* inlinerHnd, CORINFO_METHOD_STRUCT_* inlineeHnd) - { - _stashedPrecodeFixups.Push(_precodeFixups); - _precodeFixups = null; - _stashedInlinedMethods.Push(_inlinedMethods); - _inlinedMethods = null; - } - private void reportInliningDecision(CORINFO_METHOD_STRUCT_* inlinerHnd, CORINFO_METHOD_STRUCT_* inlineeHnd, CorInfoInline inlineResult, byte* reason) { if (inlineResult == CorInfoInline.INLINE_PASS) { // We deliberately ignore inlinerHnd because we have no interest to track intermediate links now. MethodDesc inlinee = HandleToObject(inlineeHnd); - - // If during inlining we found Precode fixups, then only if the inline was successful, add them to the set of - // fixups that will be used for the entire method - List previouslyStashedFixups = _stashedPrecodeFixups.Pop(); - - if (_precodeFixups != null) - { - previouslyStashedFixups = previouslyStashedFixups ?? new List(); - previouslyStashedFixups.AddRange(_precodeFixups); - } - _precodeFixups = previouslyStashedFixups; - - // If during inlining we found new inlinees, then if the inline was successful, add them to the set of fixups - // for the entire method. - HashSet previouslyStashedInlinees = _stashedInlinedMethods.Pop(); - if (_inlinedMethods != null) - { - previouslyStashedInlinees = previouslyStashedInlinees ?? new HashSet(); - foreach (var inlineeInHashSet in _inlinedMethods) - previouslyStashedInlinees.Add(inlineeInHashSet); - } - _inlinedMethods = previouslyStashedInlinees; - - // Then add the fact we inlined this method. - _inlinedMethods = _inlinedMethods ?? new HashSet(); _inlinedMethods.Add(inlinee); } - else - { - // If we didn't succeed on the inline, just pop back to the state before inlining - _precodeFixups = _stashedPrecodeFixups.Pop(); - _inlinedMethods = _stashedInlinedMethods.Pop(); - } } private void updateEntryPointForTailCall(ref CORINFO_CONST_LOOKUP entryPoint) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index c2845403c2a55..f6eeb8343c0b1 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -1854,10 +1854,19 @@ private void getAddressOfPInvokeTarget(CORINFO_METHOD_STRUCT_* method, ref CORIN private void getGSCookie(IntPtr* pCookieVal, IntPtr** ppCookieVal) { - if (ppCookieVal != null) + // TODO: fully implement GS cookies + + if (pCookieVal != null) { - *ppCookieVal = (IntPtr*)ObjectToHandle(_compilation.NodeFactory.ExternSymbol("__security_cookie")); - *pCookieVal = IntPtr.Zero; + if (PointerSize == 4) + { + *pCookieVal = (IntPtr)0x3F796857; + } + else + { + *pCookieVal = unchecked((IntPtr)0x216D6F6D202C6948); + } + *ppCookieVal = null; } else { @@ -1970,10 +1979,6 @@ private void setEHinfo(uint EHnumber, ref CORINFO_EH_CLAUSE clause) _ehClauses[EHnumber] = clause; } - private void beginInlining(CORINFO_METHOD_STRUCT_* inlinerHnd, CORINFO_METHOD_STRUCT_* inlineeHnd) - { - } - private void reportInliningDecision(CORINFO_METHOD_STRUCT_* inlinerHnd, CORINFO_METHOD_STRUCT_* inlineeHnd, CorInfoInline inlineResult, byte* reason) { } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/Signature.il b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/Signature.il index 5a528fda34d77..32e307b7036c8 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/Signature.il +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/Signature.il @@ -39,8 +39,6 @@ { ret } - - .field private bool modreq([CoreTestAssembly]System.Void) fieldWithModOpt } .class private auto ansi beforefieldinit Atom diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/SignatureTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/SignatureTests.cs index 23e1a9f58cfe2..ac8d2bc168372 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/SignatureTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/SignatureTests.cs @@ -197,35 +197,6 @@ public void TestSerializedSignatureWithReferenceToMDIntArray() Assert.Equal(typeInLookupContext, int32ArrayFromLookup); } - [Fact] - public void TestSerializedSignatureWithReferenceToFieldWithModOpt() - { - - MetadataType modOptTester = _testModule.GetType("", "ModOptTester"); - FieldDesc fieldWithModOpt = modOptTester.GetFields().Single(m => string.Equals(m.Name, "fieldWithModOpt")); - - // Create assembly with reference to interesting method - TypeSystemMetadataEmitter metadataEmitter = new TypeSystemMetadataEmitter(new System.Reflection.AssemblyName("Lookup"), _context); - var token = metadataEmitter.GetFieldRef(fieldWithModOpt); - MemoryStream peStream = new MemoryStream(); - metadataEmitter.SerializeToStream(peStream); - - peStream.Seek(0, SeekOrigin.Begin); - - // Create new TypeSystemContext with just created assembly inside - var lookupContext = new TestTypeSystemContext(TargetArchitecture.X64); - var systemModule = lookupContext.CreateModuleForSimpleName("CoreTestAssembly"); - lookupContext.SetSystemModule(systemModule); - - lookupContext.CreateModuleForSimpleName("Lookup", peStream); - - // Use generated assembly to trigger a load through the token created above and verify that it loads correctly - var ilLookupModule = (EcmaModule)lookupContext.GetModuleForSimpleName("Lookup"); - FieldDesc fieldFound = ilLookupModule.GetField(token); - - Assert.Equal("fieldWithModOpt", fieldFound.Name); - } - [Fact] public void TestMDArrayFunctionReading() { diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index eb3643851fd50..925fd5c9a90d8 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -53,8 +53,9 @@ internal class Program private string _mapFileName; private string _metadataLogFileName; private bool _noMetadataBlocking; - private string _reflectionData; + private bool _disableReflection; private bool _completeTypesMetadata; + private bool _reflectedOnly; private bool _scanReflection; private bool _methodBodyFolding; private int _parallelism = Environment.ProcessorCount; @@ -158,8 +159,6 @@ private void InitializeDefaultOptions() private ArgumentSyntax ParseCommandLine(string[] args) { - var validReflectionDataOptions = new string[] { "all", "none" }; - IReadOnlyList inputFiles = Array.Empty(); IReadOnlyList referenceFiles = Array.Empty(); @@ -202,8 +201,9 @@ private ArgumentSyntax ParseCommandLine(string[] args) syntax.DefineOption("map", ref _mapFileName, "Generate a map file"); syntax.DefineOption("metadatalog", ref _metadataLogFileName, "Generate a metadata log file"); syntax.DefineOption("nometadatablocking", ref _noMetadataBlocking, "Ignore metadata blocking for internal implementation details"); + syntax.DefineOption("disablereflection", ref _disableReflection, "Disable generation of reflection metadata"); syntax.DefineOption("completetypemetadata", ref _completeTypesMetadata, "Generate complete metadata for types"); - syntax.DefineOption("reflectiondata", ref _reflectionData, $"Reflection data to generate (one of: {string.Join(", ", validReflectionDataOptions)})"); + syntax.DefineOption("reflectedonly", ref _reflectedOnly, "Generate metadata only for reflected members"); syntax.DefineOption("scanreflection", ref _scanReflection, "Scan IL for reflection patterns"); syntax.DefineOption("scan", ref _useScanner, "Use IL scanner to generate optimized code (implied by -O)"); syntax.DefineOption("noscan", ref _noScanner, "Do not use IL scanner to generate optimized code"); @@ -342,11 +342,6 @@ private ArgumentSyntax ParseCommandLine(string[] args) Helpers.MakeReproPackage(_makeReproPath, _outputFilePath, args, argSyntax, new[] { "-r", "-m", "--rdxml", "--directpinvokelist" }); } - if (_reflectionData != null && Array.IndexOf(validReflectionDataOptions, _reflectionData) < 0) - { - Console.WriteLine($"Warning: option '{_reflectionData}' not recognized"); - } - return argSyntax; } @@ -532,7 +527,7 @@ private int Run(string[] args) InstructionSetSupportBuilder.GetNonSpecifiableInstructionSetsForArch(_targetArchitecture), _targetArchitecture); - bool supportsReflection = _reflectionData != "none" && _systemModuleName == DefaultSystemModule; + bool supportsReflection = !_disableReflection && _systemModuleName == DefaultSystemModule; // // Initialize type system context @@ -763,8 +758,8 @@ static string ILLinkify(string rootedAssembly) metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.CompleteTypesOnly; if (_scanReflection) metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.ReflectionILScanning; - if (_reflectionData == "all") - metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.CreateReflectableArtifacts; + if (_reflectedOnly) + metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.ReflectedMembersOnly; if (_rootDefaultAssemblies) metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.RootDefaultAssemblies; } diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs deleted file mode 100644 index 92c4b044ba93f..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/AddedPseudoAttributeAttribute.cs +++ /dev/null @@ -1,15 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event, AllowMultiple = true, Inherited = false)] - public class AddedPseudoAttributeAttribute : BaseExpectedLinkedBehaviorAttribute - { - public AddedPseudoAttributeAttribute (uint value) - { - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs deleted file mode 100644 index 9a963f6105571..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseExpectedLinkedBehaviorAttribute.cs +++ /dev/null @@ -1,16 +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.Diagnostics; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Base attribute for attributes that mark up the expected behavior of the linker on a member - /// - [Conditional ("INCLUDE_EXPECTATIONS")] - public abstract class BaseExpectedLinkedBehaviorAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs deleted file mode 100644 index 1d8ed24b3645c..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseInAssemblyAttribute.cs +++ /dev/null @@ -1,9 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - public abstract class BaseInAssemblyAttribute : BaseExpectedLinkedBehaviorAttribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseMemberAssertionAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseMemberAssertionAttribute.cs deleted file mode 100644 index 5afd16cfd6d9e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/BaseMemberAssertionAttribute.cs +++ /dev/null @@ -1,15 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// A base class for attributes that make assertions about a particular member. - // The test infrastructure is expected to check the assertion on the member to which - // the attribute is applied. - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Delegate, AllowMultiple = true)] - public abstract class BaseMemberAssertionAttribute : Attribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/CreatedMemberAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/CreatedMemberAttribute.cs deleted file mode 100644 index 9fdbb1938776e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/CreatedMemberAttribute.cs +++ /dev/null @@ -1,18 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true, Inherited = false)] - public sealed class CreatedMemberAttribute : BaseExpectedLinkedBehaviorAttribute - { - - public CreatedMemberAttribute (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (name)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DependencyRecordedAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DependencyRecordedAttribute.cs deleted file mode 100644 index 7220234672566..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DependencyRecordedAttribute.cs +++ /dev/null @@ -1,20 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class DependencyRecordedAttribute : BaseExpectedLinkedBehaviorAttribute - { - public DependencyRecordedAttribute (string source, string target, string marked = null) - { - if (string.IsNullOrEmpty (source)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (source)); - - if (string.IsNullOrEmpty (target)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (target)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DisplayNameAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DisplayNameAttribute.cs deleted file mode 100644 index 3e369a539e630..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/DisplayNameAttribute.cs +++ /dev/null @@ -1,12 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - public class DisplayNameAttribute : BaseMemberAssertionAttribute - { - public DisplayNameAttribute (string expectedDisplayName) - { - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/EnableLoggerAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/EnableLoggerAttribute.cs deleted file mode 100644 index 436281610fbeb..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/EnableLoggerAttribute.cs +++ /dev/null @@ -1,9 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - public abstract class EnableLoggerAttribute : BaseExpectedLinkedBehaviorAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs deleted file mode 100644 index dbe07219cf015..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectBodyModifiedAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)] - public class ExpectBodyModifiedAttribute : BaseInAssemblyAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExactlyResolvedDocumentationSignatureAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExactlyResolvedDocumentationSignatureAttribute.cs deleted file mode 100644 index b618ed7a35486..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExactlyResolvedDocumentationSignatureAttribute.cs +++ /dev/null @@ -1,14 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// Asserts that the given documentation signature string resolves to the - // member with this attribute, and only that member. - public class ExpectExactlyResolvedDocumentationSignatureAttribute : BaseMemberAssertionAttribute - { - public ExpectExactlyResolvedDocumentationSignatureAttribute (string input) - { - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs deleted file mode 100644 index a76e4b6489777..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectExceptionHandlersModifiedAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)] - public class ExpectExceptionHandlersModifiedAttribute : BaseInAssemblyAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectGeneratedDocumentationSignatureAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectGeneratedDocumentationSignatureAttribute.cs deleted file mode 100644 index c25b2ff3d0262..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectGeneratedDocumentationSignatureAttribute.cs +++ /dev/null @@ -1,14 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// Asserts that the member to which this attribute is applied has the given - /// documentation signature. - public class ExpectGeneratedDocumentationSignatureAttribute : BaseMemberAssertionAttribute - { - public ExpectGeneratedDocumentationSignatureAttribute (string expected) - { - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs deleted file mode 100644 index 56a30bd52d20c..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectLocalsModifiedAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)] - public class ExpectLocalsModifiedAttribute : BaseInAssemblyAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectResolvedDocumentationSignatureAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectResolvedDocumentationSignatureAttribute.cs deleted file mode 100644 index 5a3c16fe9bcc2..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectResolvedDocumentationSignatureAttribute.cs +++ /dev/null @@ -1,14 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// Asserts that the given documentation signature string resolves to the - // member with this attribute. - public class ExpectResolvedDocumentationSignatureAttribute : BaseMemberAssertionAttribute - { - public ExpectResolvedDocumentationSignatureAttribute (string input) - { - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectUnresolvedDocumentationSignatureAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectUnresolvedDocumentationSignatureAttribute.cs deleted file mode 100644 index aea9068451bcc..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectUnresolvedDocumentationSignatureAttribute.cs +++ /dev/null @@ -1,14 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// Asserts that the given documentation signature string does not resolve - /// to the member with this attribute. - public class ExpectUnresolvedDocumentationSignatureAttribute : BaseMemberAssertionAttribute - { - public ExpectUnresolvedDocumentationSignatureAttribute (string expected) - { - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs deleted file mode 100644 index 35ead6966a4f6..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)] - public class ExpectedInstructionSequenceAttribute : BaseInAssemblyAttribute - { - public ExpectedInstructionSequenceAttribute (string[] opCodes) - { - if (opCodes == null) - throw new ArgumentNullException (nameof (opCodes)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceOnMemberInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceOnMemberInAssemblyAttribute.cs deleted file mode 100644 index 899b979c5211e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedInstructionSequenceOnMemberInAssemblyAttribute.cs +++ /dev/null @@ -1,35 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, Inherited = false, AllowMultiple = true)] - public class ExpectedInstructionSequenceOnMemberInAssemblyAttribute : BaseInAssemblyAttribute - { - public ExpectedInstructionSequenceOnMemberInAssemblyAttribute (string assemblyFileName, Type type, string memberName, string[] opCodes) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (string.IsNullOrEmpty (memberName)) - throw new ArgumentNullException (nameof (memberName)); - if (opCodes == null) - throw new ArgumentNullException (nameof (opCodes)); - } - - public ExpectedInstructionSequenceOnMemberInAssemblyAttribute (string assemblyFileName, string typeName, string memberName, string[] opCodes) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - if (string.IsNullOrEmpty (typeName)) - throw new ArgumentNullException (nameof (typeName)); - if (string.IsNullOrEmpty (memberName)) - throw new ArgumentNullException (nameof (memberName)); - if (opCodes == null) - throw new ArgumentNullException (nameof (opCodes)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs deleted file mode 100644 index fdd3441b71f44..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedLocalsSequenceAttribute.cs +++ /dev/null @@ -1,23 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false, AllowMultiple = false)] - public class ExpectedLocalsSequenceAttribute : BaseInAssemblyAttribute - { - public ExpectedLocalsSequenceAttribute (string[] types) - { - if (types == null) - throw new ArgumentNullException (nameof (types)); - } - - public ExpectedLocalsSequenceAttribute (Type[] types) - { - if (types == null) - throw new ArgumentNullException (nameof (types)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedNoWarningsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedNoWarningsAttribute.cs deleted file mode 100644 index cd6e8f38667b2..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedNoWarningsAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage ( - AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field, - AllowMultiple = false, - Inherited = false)] - public class ExpectedNoWarningsAttribute : EnableLoggerAttribute - { - public ExpectedNoWarningsAttribute () { } - public ExpectedNoWarningsAttribute (string warningCode) { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs deleted file mode 100644 index 94d9f1c2cf725..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ExpectedWarningAttribute.cs +++ /dev/null @@ -1,30 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage ( - AttributeTargets.Assembly | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Event, - AllowMultiple = true, - Inherited = false)] - public class ExpectedWarningAttribute : EnableLoggerAttribute - { - public ExpectedWarningAttribute (string warningCode, params string[] messageContains) - { - } - - public string FileName { get; set; } - public int SourceLine { get; set; } - public int SourceColumn { get; set; } - - /// - /// Property used by the result checkers of trimmer and analyzers to determine whether - /// the tool should have produced the specified warning on the annotated member. - /// - public ProducedBy ProducedBy { get; set; } = ProducedBy.TrimmerAnalyzerAndNativeAot; - - public bool CompilerGeneratedCode { get; set; } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs deleted file mode 100644 index 78fd0e4537423..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/IgnoreTestCaseAttribute.cs +++ /dev/null @@ -1,18 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class)] - public class IgnoreTestCaseAttribute : Attribute - { - - public IgnoreTestCaseAttribute (string reason) - { - if (reason == null) - throw new ArgumentNullException (nameof (reason)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs deleted file mode 100644 index ffdb9d07c2e0a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAllTypesAndMembersInAssemblyAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)] - public class KeptAllTypesAndMembersInAssemblyAttribute : BaseInAssemblyAttribute - { - public KeptAllTypesAndMembersInAssemblyAttribute (string assemblyFileName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs deleted file mode 100644 index 9103fa1c31763..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAssemblyAttribute.cs +++ /dev/null @@ -1,21 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that an assembly does exist in the output directory - /// - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)] - public class KeptAssemblyAttribute : KeptAttribute - { - - public KeptAssemblyAttribute (string fileName) - { - if (string.IsNullOrEmpty (fileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (fileName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs deleted file mode 100644 index 922123f7d11bd..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.All, Inherited = false)] - public class KeptAttribute : BaseExpectedLinkedBehaviorAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs deleted file mode 100644 index 0b5943a5a1a5e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeAttribute.cs +++ /dev/null @@ -1,24 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.All, AllowMultiple = true, Inherited = false)] - public class KeptAttributeAttribute : KeptAttribute - { - - public KeptAttributeAttribute (string attributeName) - { - if (string.IsNullOrEmpty (attributeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (attributeName)); - } - - public KeptAttributeAttribute (Type type) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs deleted file mode 100644 index 91081f68a1416..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeInAssemblyAttribute.cs +++ /dev/null @@ -1,71 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptAttributeInAssemblyAttribute : BaseInAssemblyAttribute - { - /// - /// Asserts a CustomAttribute was kept on an assembly - /// - /// - /// - public KeptAttributeInAssemblyAttribute (string assemblyName, string attributeTypeName) - { - } - - /// - /// Asserts a CustomAttribute was kept on an assembly - /// - /// - /// - public KeptAttributeInAssemblyAttribute (string assemblyName, Type attributeType) - { - } - - /// - /// Asserts a CustomAttribute was kept on a specific type - /// - /// - /// - /// - public KeptAttributeInAssemblyAttribute (string assemblyName, string attributeTypeName, string onType) - { - } - - /// - /// Asserts a CustomAttribute was kept on a specific type - /// - /// - /// - /// - public KeptAttributeInAssemblyAttribute (string assemblyName, Type attributeType, Type onType) - { - } - - /// - /// Asserts a CustomAttribute was kept on a member in a specific type - /// - /// - /// - /// - /// - public KeptAttributeInAssemblyAttribute (string assemblyName, string attributeTypeName, string onType, string member) - { - } - - /// - /// Asserts a CustomAttribute was kept on a member in a specific type - /// - /// - /// - /// - /// - public KeptAttributeInAssemblyAttribute (string assemblyName, Type attributeType, Type onType, string member) - { - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs deleted file mode 100644 index 0fc56741a8ca4..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptAttributeOnFixedBufferTypeAttribute.cs +++ /dev/null @@ -1,23 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Field, Inherited = false, AllowMultiple = true)] - public class KeptAttributeOnFixedBufferTypeAttribute : KeptAttribute - { - public KeptAttributeOnFixedBufferTypeAttribute (string attributeName) - { - if (string.IsNullOrEmpty (attributeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (attributeName)); - } - - public KeptAttributeOnFixedBufferTypeAttribute (Type type) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs deleted file mode 100644 index 6994e1201f16e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBackingFieldAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Property | AttributeTargets.Event, AllowMultiple = false, Inherited = false)] - public sealed class KeptBackingFieldAttribute : KeptAttribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs deleted file mode 100644 index acac5d575bbce..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseOnTypeInAssemblyAttribute.cs +++ /dev/null @@ -1,37 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptBaseOnTypeInAssemblyAttribute : BaseInAssemblyAttribute - { - public KeptBaseOnTypeInAssemblyAttribute (string assemblyFileName, Type type, string baseAssemblyFileName, Type baseType) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - - if (string.IsNullOrEmpty (baseAssemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (baseAssemblyFileName)); - if (baseType == null) - throw new ArgumentException ("Value cannot be null or empty.", nameof (baseType)); - } - - public KeptBaseOnTypeInAssemblyAttribute (string assemblyFileName, string typeName, string baseAssemblyFileName, string baseTypeName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - if (string.IsNullOrEmpty (typeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName)); - - if (string.IsNullOrEmpty (baseAssemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (baseAssemblyFileName)); - if (string.IsNullOrEmpty (baseTypeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (baseTypeName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs deleted file mode 100644 index c4e4a24889542..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptBaseTypeAttribute.cs +++ /dev/null @@ -1,25 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Enum, AllowMultiple = false, Inherited = false)] - public sealed class KeptBaseTypeAttribute : KeptAttribute - { - public KeptBaseTypeAttribute (Type baseType) - { - if (baseType == null) - throw new ArgumentNullException (nameof (baseType)); - } - - public KeptBaseTypeAttribute (Type baseType, params object[] typeArguments) - { - if (baseType == null) - throw new ArgumentNullException (nameof (baseType)); - if (typeArguments == null) - throw new ArgumentNullException (nameof (typeArguments)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs deleted file mode 100644 index 52fe496182f8b..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptDelegateCacheFieldAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = true)] - public class KeptDelegateCacheFieldAttribute : KeptAttribute - { - public KeptDelegateCacheFieldAttribute (string uniquePartOfName) - { - if (string.IsNullOrEmpty (uniquePartOfName)) - throw new ArgumentNullException (nameof (uniquePartOfName)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs deleted file mode 100644 index 2b745838c9666..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventAddMethodAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Event, Inherited = false, AllowMultiple = false)] - public class KeptEventAddMethodAttribute : KeptAttribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs deleted file mode 100644 index 0cbcdd171a91e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptEventRemoveMethodAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Event, Inherited = false, AllowMultiple = false)] - public class KeptEventRemoveMethodAttribute : KeptAttribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptExportedTypeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptExportedTypeAttribute.cs deleted file mode 100644 index 76dbe921c9457..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptExportedTypeAttribute.cs +++ /dev/null @@ -1,20 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that a module reference exists in the test case assembly - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptExportedTypeAttribute : KeptAttribute - { - public KeptExportedTypeAttribute (Type type) - { - if (type is null) - throw new ArgumentNullException (nameof (type)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs deleted file mode 100644 index d0067544ad760..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptFixedBufferAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Field, Inherited = false, AllowMultiple = false)] - public class KeptFixedBufferAttribute : KeptAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs deleted file mode 100644 index 25b8c8261f16c..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInitializerData.cs +++ /dev/null @@ -1,22 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Method, AllowMultiple = true, Inherited = false)] - public class KeptInitializerData : KeptAttribute - { - - public KeptInitializerData () - { - } - - public KeptInitializerData (int occurrenceIndexInBody) - { - if (occurrenceIndexInBody < 0) - throw new ArgumentOutOfRangeException (nameof (occurrenceIndexInBody)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs deleted file mode 100644 index 85279abcd83f6..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceAttribute.cs +++ /dev/null @@ -1,26 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)] - public class KeptInterfaceAttribute : KeptAttribute - { - - public KeptInterfaceAttribute (Type interfaceType) - { - if (interfaceType == null) - throw new ArgumentNullException (nameof (interfaceType)); - } - - public KeptInterfaceAttribute (Type interfaceType, params object[] typeArguments) - { - if (interfaceType == null) - throw new ArgumentNullException (nameof (interfaceType)); - if (typeArguments == null) - throw new ArgumentNullException (nameof (typeArguments)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs deleted file mode 100644 index 2741439facc88..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptInterfaceOnTypeInAssemblyAttribute.cs +++ /dev/null @@ -1,37 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptInterfaceOnTypeInAssemblyAttribute : BaseInAssemblyAttribute - { - public KeptInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, Type type, string interfaceAssemblyFileName, Type interfaceType) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - - if (string.IsNullOrEmpty (interfaceAssemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName)); - if (interfaceType == null) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceType)); - } - - public KeptInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, string typeName, string interfaceAssemblyFileName, string interfaceTypeName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - if (string.IsNullOrEmpty (typeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName)); - - if (string.IsNullOrEmpty (interfaceAssemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName)); - if (string.IsNullOrEmpty (interfaceTypeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceTypeName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs deleted file mode 100644 index 6f7adcf30bedb..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberAttribute.cs +++ /dev/null @@ -1,18 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate | AttributeTargets.Struct | AttributeTargets.Enum, AllowMultiple = true, Inherited = false)] - public sealed class KeptMemberAttribute : KeptAttribute - { - - public KeptMemberAttribute (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (name)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs deleted file mode 100644 index b8e38f5788c05..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptMemberInAssemblyAttribute.cs +++ /dev/null @@ -1,34 +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; - - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)] - public class KeptMemberInAssemblyAttribute : BaseInAssemblyAttribute - { - public KeptMemberInAssemblyAttribute (string assemblyFileName, Type type, params string[] memberNames) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (memberNames == null) - throw new ArgumentNullException (nameof (memberNames)); - } - - public KeptMemberInAssemblyAttribute (string assemblyFileName, string typeName, params string[] memberNames) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - if (typeName == null) - throw new ArgumentNullException (nameof (typeName)); - if (memberNames == null) - throw new ArgumentNullException (nameof (memberNames)); - } - - public string ExpectationAssemblyName { get; set; } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptModuleReferenceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptModuleReferenceAttribute.cs deleted file mode 100644 index 4ebab7d971608..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptModuleReferenceAttribute.cs +++ /dev/null @@ -1,20 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that a module reference exists in the test case assembly - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptModuleReferenceAttribute : KeptAttribute - { - public KeptModuleReferenceAttribute (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (name)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs deleted file mode 100644 index f4bb464260dba..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferenceAttribute.cs +++ /dev/null @@ -1,20 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that a reference exists in the test case assembly - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptReferenceAttribute : KeptAttribute - { - public KeptReferenceAttribute (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (name)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs deleted file mode 100644 index 0265b9f3a40d9..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptReferencesInAssemblyAttribute.cs +++ /dev/null @@ -1,20 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptReferencesInAssemblyAttribute : BaseInAssemblyAttribute - { - public KeptReferencesInAssemblyAttribute (string assemblyFileName, string[] expectedReferenceAssemblyNames) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - - if (expectedReferenceAssemblyNames == null) - throw new ArgumentNullException (nameof (expectedReferenceAssemblyNames)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs deleted file mode 100644 index bcbbd20fb7253..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceAttribute.cs +++ /dev/null @@ -1,20 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that a resource exists in the test case assembly - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptResourceAttribute : KeptAttribute - { - public KeptResourceAttribute (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (name)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs deleted file mode 100644 index fa95216e3e3b5..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptResourceInAssemblyAttribute.cs +++ /dev/null @@ -1,23 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that an embedded resource exists in an assembly - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptResourceInAssemblyAttribute : BaseInAssemblyAttribute - { - public KeptResourceInAssemblyAttribute (string assemblyFileName, string resourceName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - - if (string.IsNullOrEmpty (resourceName)) - throw new ArgumentNullException (nameof (resourceName)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs deleted file mode 100644 index 05519377252dc..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSecurityAttribute.cs +++ /dev/null @@ -1,23 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = true, Inherited = false)] - public class KeptSecurityAttribute : KeptAttribute - { - public KeptSecurityAttribute (string attributeName) - { - if (string.IsNullOrEmpty (attributeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (attributeName)); - } - - public KeptSecurityAttribute (Type type) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs deleted file mode 100644 index 3e435017b8b57..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptSymbolsAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class KeptSymbolsAttribute : KeptAttribute - { - public KeptSymbolsAttribute (string assemblyFileName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs deleted file mode 100644 index 5be0adc4aa108..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/KeptTypeInAssemblyAttribute.cs +++ /dev/null @@ -1,27 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)] - public class KeptTypeInAssemblyAttribute : BaseInAssemblyAttribute - { - public KeptTypeInAssemblyAttribute (string assemblyFileName, Type type) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - } - - public KeptTypeInAssemblyAttribute (string assemblyFileName, string typeName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - if (string.IsNullOrEmpty (typeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs deleted file mode 100644 index de9b8478bfd13..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogContainsAttribute.cs +++ /dev/null @@ -1,26 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage ( - AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field, - AllowMultiple = true, - Inherited = false)] - public class LogContainsAttribute : EnableLoggerAttribute - { - public LogContainsAttribute (string message, bool regexMatch = false) - { - if (string.IsNullOrEmpty (message)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (message)); - } - - /// - /// Property used by the result checkers of trimmer and analyzers to determine whether - /// the tool should have produced the specified warning on the annotated member. - /// - public ProducedBy ProducedBy { get; set; } = ProducedBy.TrimmerAnalyzerAndNativeAot; - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs deleted file mode 100644 index c5b47210ed846..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/LogDoesNotContainAttribute.cs +++ /dev/null @@ -1,26 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage ( - AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor | AttributeTargets.Field, - AllowMultiple = true, - Inherited = false)] - public class LogDoesNotContainAttribute : EnableLoggerAttribute - { - public LogDoesNotContainAttribute (string message, bool regexMatch = false) - { - if (string.IsNullOrEmpty (message)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (message)); - } - - /// - /// Property used by the result checkers of trimmer and analyzers to determine whether - /// the tool should have produced the specified warning on the annotated member. - /// - public ProducedBy ProducedBy { get; set; } = ProducedBy.TrimmerAnalyzerAndNativeAot; - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/NoLinkedOutputAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/NoLinkedOutputAttribute.cs deleted file mode 100644 index 85334c97da7ca..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/NoLinkedOutputAttribute.cs +++ /dev/null @@ -1,13 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class)] - public class NoLinkedOutputAttribute : Attribute - { - public NoLinkedOutputAttribute () { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs deleted file mode 100644 index 7840516cc242a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/ProducedBy.cs +++ /dev/null @@ -1,21 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Used to specify which tool produces a warning. This can either be the trimmer, a specific analyzer, or both. - /// Currently we have all existing diagnostic analyzers listed in here so that we can leave out some expected warnings - /// when testing analyzers which do not produce them. - /// - [Flags] - public enum ProducedBy - { - Trimmer = 1, - Analyzer = 2, - NativeAot = 4, - TrimmerAnalyzerAndNativeAot = Trimmer | Analyzer | NativeAot - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs deleted file mode 100644 index e1dc4c0e1e36a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyAttribute.cs +++ /dev/null @@ -1,21 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that an assembly does not exist in the output directory - /// - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)] - public class RemovedAssemblyAttribute : BaseExpectedLinkedBehaviorAttribute - { - - public RemovedAssemblyAttribute (string fileName) - { - if (string.IsNullOrEmpty (fileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (fileName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyReference.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyReference.cs deleted file mode 100644 index 4bb914493a45d..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAssemblyReference.cs +++ /dev/null @@ -1,18 +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; -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class RemovedAssemblyReferenceAttribute : BaseInAssemblyAttribute - { - public RemovedAssemblyReferenceAttribute (string assemblyFileName, string assemblyReferenceName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - if (string.IsNullOrEmpty (assemblyReferenceName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyReferenceName)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs deleted file mode 100644 index 591aa81b40f0e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedAttributeInAssembly.cs +++ /dev/null @@ -1,71 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class RemovedAttributeInAssembly : BaseInAssemblyAttribute - { - /// - /// Asserts a CustomAttribute was kept on an assembly - /// - /// - /// - public RemovedAttributeInAssembly (string assemblyName, string attributeTypeName) - { - } - - /// - /// Asserts a CustomAttribute was kept on an assembly - /// - /// - /// - public RemovedAttributeInAssembly (string assemblyName, Type attributeType) - { - } - - /// - /// Asserts a CustomAttribute was kept on a specific type - /// - /// - /// - /// - public RemovedAttributeInAssembly (string assemblyName, string attributeTypeName, string onType) - { - } - - /// - /// Asserts a CustomAttribute was kept on a specific type - /// - /// - /// - /// - public RemovedAttributeInAssembly (string assemblyName, Type attributeType, Type onType) - { - } - - /// - /// Asserts a CustomAttribute was kept on a member in a specific type - /// - /// - /// - /// - /// - public RemovedAttributeInAssembly (string assemblyName, string attributeTypeName, string onType, string member) - { - } - - /// - /// Asserts a CustomAttribute was kept on a member in a specific type - /// - /// - /// - /// - /// - public RemovedAttributeInAssembly (string assemblyName, Type attributeType, Type onType, string member) - { - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs deleted file mode 100644 index eb9a394473623..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedForwarderAttribute.cs +++ /dev/null @@ -1,18 +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; -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class RemovedForwarderAttribute : BaseInAssemblyAttribute - { - public RemovedForwarderAttribute (string assemblyFileName, string typeName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - if (string.IsNullOrEmpty (typeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs deleted file mode 100644 index 70465fc3d6035..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedInterfaceOnTypeInAssemblyAttribute.cs +++ /dev/null @@ -1,37 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class RemovedInterfaceOnTypeInAssemblyAttribute : BaseInAssemblyAttribute - { - public RemovedInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, Type type, string interfaceAssemblyFileName, Type interfaceType) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - - if (string.IsNullOrEmpty (interfaceAssemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName)); - if (interfaceType == null) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceType)); - } - - public RemovedInterfaceOnTypeInAssemblyAttribute (string assemblyFileName, string typeName, string interfaceAssemblyFileName, string interfaceTypeName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - if (string.IsNullOrEmpty (typeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName)); - - if (string.IsNullOrEmpty (interfaceAssemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceAssemblyFileName)); - if (string.IsNullOrEmpty (interfaceTypeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (interfaceTypeName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs deleted file mode 100644 index fe0deb6374aaf..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedMemberInAssemblyAttribute.cs +++ /dev/null @@ -1,32 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)] - public class RemovedMemberInAssemblyAttribute : BaseInAssemblyAttribute - { - - public RemovedMemberInAssemblyAttribute (string assemblyFileName, Type type, params string[] memberNames) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (memberNames == null) - throw new ArgumentNullException (nameof (memberNames)); - } - - public RemovedMemberInAssemblyAttribute (string assemblyFileName, string typeName, params string[] memberNames) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - if (typeName == null) - throw new ArgumentNullException (nameof (typeName)); - if (memberNames == null) - throw new ArgumentNullException (nameof (memberNames)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedNameValueAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedNameValueAttribute.cs deleted file mode 100644 index 027bd35955801..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedNameValueAttribute.cs +++ /dev/null @@ -1,15 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that name of the member is removed - /// - [AttributeUsage (AttributeTargets.All, AllowMultiple = false, Inherited = false)] - public class RemovedNameValueAttribute : BaseExpectedLinkedBehaviorAttribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs deleted file mode 100644 index 00b4eb588eaf7..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedPseudoAttributeAttribute.cs +++ /dev/null @@ -1,15 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Interface | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event, AllowMultiple = true, Inherited = false)] - public class RemovedPseudoAttributeAttribute : BaseExpectedLinkedBehaviorAttribute - { - public RemovedPseudoAttributeAttribute (uint value) - { - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs deleted file mode 100644 index 5b793a034964d..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedResourceInAssemblyAttribute.cs +++ /dev/null @@ -1,23 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - /// - /// Verifies that an embedded resource was removed from an assembly - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class RemovedResourceInAssemblyAttribute : BaseInAssemblyAttribute - { - public RemovedResourceInAssemblyAttribute (string assemblyFileName, string resourceName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentNullException (nameof (assemblyFileName)); - - if (string.IsNullOrEmpty (resourceName)) - throw new ArgumentNullException (nameof (resourceName)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs deleted file mode 100644 index 1549b8a03c9f1..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedSymbolsAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true, Inherited = false)] - public class RemovedSymbolsAttribute : BaseExpectedLinkedBehaviorAttribute - { - public RemovedSymbolsAttribute (string assemblyFileName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs deleted file mode 100644 index 079ba5d1f0b7d..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/RemovedTypeInAssemblyAttribute.cs +++ /dev/null @@ -1,27 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false)] - public class RemovedTypeInAssemblyAttribute : BaseInAssemblyAttribute - { - public RemovedTypeInAssemblyAttribute (string assemblyFileName, Type type) - { - if (type == null) - throw new ArgumentNullException (nameof (type)); - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - } - - public RemovedTypeInAssemblyAttribute (string assemblyFileName, string typeName) - { - if (string.IsNullOrEmpty (assemblyFileName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (assemblyFileName)); - if (string.IsNullOrEmpty (typeName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (typeName)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipKeptItemsValidationAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipKeptItemsValidationAttribute.cs deleted file mode 100644 index deb54564a8d0a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipKeptItemsValidationAttribute.cs +++ /dev/null @@ -1,13 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SkipKeptItemsValidationAttribute : BaseExpectedLinkedBehaviorAttribute - { - public SkipKeptItemsValidationAttribute () { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs deleted file mode 100644 index 5b293eacdd349..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipPeVerifyAttribute.cs +++ /dev/null @@ -1,29 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - - public enum SkipPeVerifyForToolchian - { - Pedump - } - - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SkipPeVerifyAttribute : BaseExpectedLinkedBehaviorAttribute - { - public SkipPeVerifyAttribute () - { - } - - public SkipPeVerifyAttribute (SkipPeVerifyForToolchian toolchain) - { - } - - public SkipPeVerifyAttribute (string assemblyName) - { - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipRemainingErrorsValidationAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipRemainingErrorsValidationAttribute.cs deleted file mode 100644 index 09174ab0577d0..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/SkipRemainingErrorsValidationAttribute.cs +++ /dev/null @@ -1,13 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SkipRemainingErrorsValidationAttribute : BaseExpectedLinkedBehaviorAttribute - { - public SkipRemainingErrorsValidationAttribute () { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestCaseRequirementsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestCaseRequirementsAttribute.cs deleted file mode 100644 index 9e766c9ce05c6..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestCaseRequirementsAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class)] - public class TestCaseRequirementsAttribute : BaseExpectedLinkedBehaviorAttribute - { - public TestCaseRequirementsAttribute (TestRunCharacteristics targetFrameworkCharacteristics, string reason) - { - if (reason == null) - throw new ArgumentNullException (nameof (reason)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestRunCharacteristics.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestRunCharacteristics.cs deleted file mode 100644 index 1e35a3dda0042..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/TestRunCharacteristics.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [Flags] - public enum TestRunCharacteristics - { - TargetingNetFramework = 1, - TargetingNetCore = 2, - SupportsDefaultInterfaceMethods = 8, - SupportsStaticInterfaceMethods = 16, - TestFrameworkSupportsMcs = 32 - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/VerifyMetadataNamesAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/VerifyMetadataNamesAttribute.cs deleted file mode 100644 index bf42f4da0545f..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Assertions/VerifyMetadataNamesAttribute.cs +++ /dev/null @@ -1,15 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Assertions -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false, Inherited = false)] - public class VerifyMetadataNamesAttribute : BaseExpectedLinkedBehaviorAttribute - { - public VerifyMetadataNamesAttribute () - { - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowStringExtensions.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowStringExtensions.cs deleted file mode 100644 index aa9c0b081f50a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowStringExtensions.cs +++ /dev/null @@ -1,42 +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.Diagnostics.CodeAnalysis; - -namespace Mono.Linker.Tests.Cases.Expectations.Helpers -{ - public static class DataFlowStringExtensions - { - public static void RequiresAll ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] this string str) { } - - public static void RequiresPublicConstructors ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] this string str) { } - - public static void RequiresPublicEvents ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] this string str) { } - - public static void RequiresPublicFields ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] this string str) { } - - public static void RequiresPublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] this string str) { } - - public static void RequiresPublicNestedTypes ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicNestedTypes)] this string str) { } - - public static void RequiresPublicParameterlessConstructor ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] this string str) { } - - public static void RequiresPublicProperties ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] this string str) { } - - public static void RequiresNonPublicEvents ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicEvents)] this string str) { } - - public static void RequiresNonPublicFields ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicFields)] this string str) { } - - public static void RequiresNonPublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] this string str) { } - - public static void RequiresNonPublicNestedTypes ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] this string str) { } - - public static void RequiresNonPublicConstructors ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] this string str) { } - - public static void RequiresNonPublicProperties ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicProperties)] this string str) { } - - public static void RequiresInterfaces ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] this string str) { } - - public static void RequiresNone (this string str) { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowTypeExtensions.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowTypeExtensions.cs deleted file mode 100644 index e11f78abe89ad..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/DataFlowTypeExtensions.cs +++ /dev/null @@ -1,43 +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.Diagnostics.CodeAnalysis; - -namespace Mono.Linker.Tests.Cases.Expectations.Helpers -{ - public static class DataFlowTypeExtensions - { - public static void RequiresAll ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] this Type type) { } - - public static void RequiresPublicConstructors ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] this Type type) { } - - public static void RequiresPublicEvents ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] this Type type) { } - - public static void RequiresPublicFields ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] this Type type) { } - - public static void RequiresPublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] this Type type) { } - - public static void RequiresPublicNestedTypes ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicNestedTypes)] this Type type) { } - - public static void RequiresPublicParameterlessConstructor ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] this Type type) { } - - public static void RequiresPublicProperties ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] this Type type) { } - - public static void RequiresNonPublicEvents ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicEvents)] this Type type) { } - - public static void RequiresNonPublicFields ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicFields)] this Type type) { } - - public static void RequiresNonPublicMethods ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] this Type type) { } - - public static void RequiresNonPublicNestedTypes ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] this Type type) { } - - public static void RequiresNonPublicConstructors ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] this Type type) { } - - public static void RequiresNonPublicProperties ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicProperties)] this Type type) { } - - public static void RequiresInterfaces ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] this Type type) { } - - public static void RequiresNone (this Type type) { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs deleted file mode 100644 index c2e77e98f8d44..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Helpers/PlatformAssemblies.cs +++ /dev/null @@ -1,14 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Helpers -{ - public static class PlatformAssemblies - { -#if NETCOREAPP - public const string CoreLib = "System.Private.CoreLib.dll"; -#else - public const string CoreLib = "mscorlib.dll"; -#endif - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs deleted file mode 100644 index d29e0a0ec6fad..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/BaseMetadataAttribute.cs +++ /dev/null @@ -1,13 +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.Diagnostics; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [Conditional ("INCLUDE_EXPECTATIONS")] - public abstract class BaseMetadataAttribute : Attribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs deleted file mode 100644 index f0e34d1e68b4a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/DefineAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class DefineAttribute : BaseMetadataAttribute - { - public DefineAttribute (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (name)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreDescriptorsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreDescriptorsAttribute.cs deleted file mode 100644 index ef1656e564c00..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreDescriptorsAttribute.cs +++ /dev/null @@ -1,15 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - public sealed class IgnoreDescriptorsAttribute : BaseMetadataAttribute - { - public readonly bool Value; - - public IgnoreDescriptorsAttribute (bool value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreLinkAttributesAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreLinkAttributesAttribute.cs deleted file mode 100644 index 0679c0f52d868..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreLinkAttributesAttribute.cs +++ /dev/null @@ -1,15 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - public sealed class IgnoreLinkAttributesAttribute : BaseMetadataAttribute - { - public readonly bool Value; - - public IgnoreLinkAttributesAttribute (bool value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreSubstitutionsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreSubstitutionsAttribute.cs deleted file mode 100644 index 613e9d8a908f7..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/IgnoreSubstitutionsAttribute.cs +++ /dev/null @@ -1,15 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - public sealed class IgnoreSubstitutionsAttribute : BaseMetadataAttribute - { - public readonly bool Value; - - public IgnoreSubstitutionsAttribute (bool value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs deleted file mode 100644 index d79cdb37f1c2f..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/Il8nAttribute.cs +++ /dev/null @@ -1,18 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class)] - public sealed class Il8nAttribute : BaseMetadataAttribute - { - public readonly string Value; - - public Il8nAttribute (string value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs deleted file mode 100644 index e386d35024825..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/KeepTypeForwarderOnlyAssembliesAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class)] - public sealed class KeepTypeForwarderOnlyAssembliesAttribute : BaseMetadataAttribute - { - public KeepTypeForwarderOnlyAssembliesAttribute (string value) - { - if (string.IsNullOrEmpty (value)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (value)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs deleted file mode 100644 index a099ee6301a4b..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/NotATestCaseAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct)] - public class NotATestCaseAttribute : BaseMetadataAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs deleted file mode 100644 index a704ea414e823..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceAttribute.cs +++ /dev/null @@ -1,18 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class ReferenceAttribute : BaseMetadataAttribute - { - - public ReferenceAttribute (string value) - { - if (string.IsNullOrEmpty (value)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (value)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs deleted file mode 100644 index c038fe43f7504..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/ReferenceDependencyAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class ReferenceDependencyAttribute : BaseMetadataAttribute - { - public ReferenceDependencyAttribute (string value) - { - if (string.IsNullOrEmpty (value)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (value)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs deleted file mode 100644 index dce29bd3170bb..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SandboxDependencyAttribute.cs +++ /dev/null @@ -1,24 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SandboxDependencyAttribute : BaseMetadataAttribute - { - - public SandboxDependencyAttribute (string relativePathToFile, string destinationFileName = null) - { - if (string.IsNullOrEmpty (relativePathToFile)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (relativePathToFile)); - } - - public SandboxDependencyAttribute (Type typeOfSourceFileToInclude, string destinationFileName = null) - { - if (typeOfSourceFileToInclude == null) - throw new ArgumentException ("Value cannot be null or empty.", nameof (typeOfSourceFileToInclude)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs deleted file mode 100644 index 277834153aaf9..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCSharpCompilerToUseAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SetupCSharpCompilerToUseAttribute : BaseMetadataAttribute - { - public SetupCSharpCompilerToUseAttribute (string name) - { - if (string.IsNullOrEmpty (name)) - throw new ArgumentNullException (nameof (name)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs deleted file mode 100644 index 71f9f7a3854bb..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAfterAttribute.cs +++ /dev/null @@ -1,36 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - /// - /// Use to compile an assembly after compiling the main test case executabe - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupCompileAfterAttribute : BaseMetadataAttribute - { - public SetupCompileAfterAttribute (string outputName, string[] sourceFiles, string[] references = null, string[] defines = null, object[] resources = null, string additionalArguments = null, string compilerToUse = null, bool addAsReference = true, bool removeFromLinkerInput = false) - { - if (sourceFiles == null) - throw new ArgumentNullException (nameof (sourceFiles)); - - if (string.IsNullOrEmpty (outputName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (outputName)); - - if (resources != null) { - foreach (var res in resources) { - if (res is string) - continue; - if (res is string[] stringArray) { - if (stringArray.Length != 2) - throw new ArgumentException ("Entry in object[] cannot be a string[] unless it has exactly two elements, for the resource path and name", nameof (resources)); - continue; - } - throw new ArgumentException ("Each value in the object[] must be a string or a string[], either a resource path, or a path and name", nameof (resources)); - } - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs deleted file mode 100644 index 67020707d814d..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileArgumentAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupCompileArgumentAttribute : BaseMetadataAttribute - { - public SetupCompileArgumentAttribute (string value) - { - if (string.IsNullOrEmpty (value)) - throw new ArgumentNullException (nameof (value)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs deleted file mode 100644 index e78aaa089bcc3..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAsLibraryAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SetupCompileAsLibraryAttribute : BaseMetadataAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs deleted file mode 100644 index 7fad90431149d..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileAssemblyNameAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SetupCompileAssemblyNameAttribute : BaseMetadataAttribute - { - public SetupCompileAssemblyNameAttribute (string outputName) - { - if (string.IsNullOrEmpty (outputName)) - throw new ArgumentNullException (nameof (outputName)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs deleted file mode 100644 index 0021300c8403e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileBeforeAttribute.cs +++ /dev/null @@ -1,58 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - /// - /// Use to compile an assembly before compiling the main test case executabe - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupCompileBeforeAttribute : BaseMetadataAttribute - { - public SetupCompileBeforeAttribute (string outputName, string[] sourceFiles, string[] references = null, string[] defines = null, object[] resources = null, string additionalArguments = null, string compilerToUse = null, bool addAsReference = true, bool removeFromLinkerInput = false, string outputSubFolder = null) - { - if (sourceFiles == null) - throw new ArgumentNullException (nameof (sourceFiles)); - - if (string.IsNullOrEmpty (outputName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (outputName)); - - if (resources != null) { - foreach (var res in resources) { - if (res is string) - continue; - if (res is string[] stringArray) { - if (stringArray.Length != 2) - throw new ArgumentException ("Entry in object[] cannot be a string[] unless it has exactly two elements, for the resource path and name", nameof (resources)); - continue; - } - throw new ArgumentException ("Each value in the object[] must be a string or a string[], either a resource path, or a path and name", nameof (resources)); - } - } - } - - public SetupCompileBeforeAttribute (string outputName, Type[] typesToIncludeSourceFor, string[] references = null, string[] defines = null, object[] resources = null, string additionalArguments = null, string compilerToUse = null, bool addAsReference = true, bool removeFromLinkerInput = false) - { - if (typesToIncludeSourceFor == null) - throw new ArgumentNullException (nameof (typesToIncludeSourceFor)); - - if (string.IsNullOrEmpty (outputName)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (outputName)); - - if (resources != null) { - foreach (var res in resources) { - if (res is string) - continue; - if (res is string[] stringArray) { - if (stringArray.Length != 2) - throw new ArgumentException ("Entry in object[] cannot be a string[] unless it has exactly two elements, for the resource path and name", nameof (resources)); - continue; - } - throw new ArgumentException ("Each value in the object[] must be a string or a string[], either a resource path, or a path and name", nameof (resources)); - } - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs deleted file mode 100644 index 83a7f11c57e61..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupCompileResourceAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupCompileResourceAttribute : BaseMetadataAttribute - { - public SetupCompileResourceAttribute (string relativePathToFile, string destinationFileName = null) - { - if (string.IsNullOrEmpty (relativePathToFile)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (relativePathToFile)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkAttributesFile.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkAttributesFile.cs deleted file mode 100644 index 1c55f9946e658..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkAttributesFile.cs +++ /dev/null @@ -1,15 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupLinkAttributesFile : BaseMetadataAttribute - { - public SetupLinkAttributesFile (string relativePathToFile, string destinationFileName = null) - { - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs deleted file mode 100644 index bc78fc9346ff7..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerActionAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupLinkerActionAttribute : BaseMetadataAttribute - { - public SetupLinkerActionAttribute (string action, string assembly) - { - if (string.IsNullOrEmpty (action)) - throw new ArgumentNullException (nameof (action)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs deleted file mode 100644 index 6f2e55f24bba2..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerArgumentAttribute.cs +++ /dev/null @@ -1,24 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - - /// - /// Used to define arguments to pass to the linker. - /// - /// Don't use this attribute to setup single character flags. These flags do a poor job of communicating their purpose - /// and although we need to continue to support the usages that exist today, that doesn't mean we need to make our tests harder to read - /// - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupLinkerArgumentAttribute : BaseMetadataAttribute - { - public SetupLinkerArgumentAttribute (string flag, params string[] values) - { - if (string.IsNullOrEmpty (flag)) - throw new ArgumentNullException (nameof (flag)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDefaultActionAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDefaultActionAttribute.cs deleted file mode 100644 index ee9794d495f98..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDefaultActionAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SetupLinkerDefaultActionAttribute : BaseMetadataAttribute - { - public SetupLinkerDefaultActionAttribute (string action) - { - if (string.IsNullOrEmpty (action)) - throw new ArgumentNullException (nameof (action)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDescriptorFile.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDescriptorFile.cs deleted file mode 100644 index e1c7c4501dc15..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerDescriptorFile.cs +++ /dev/null @@ -1,15 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupLinkerDescriptorFile : BaseMetadataAttribute - { - public SetupLinkerDescriptorFile (string relativePathToFile, string destinationFileName = null) - { - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs deleted file mode 100644 index 2213b9cc551c7..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerKeepDebugMembersAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class)] - public class SetupLinkerKeepDebugMembersAttribute : BaseMetadataAttribute - { - public SetupLinkerKeepDebugMembersAttribute (string value) - { - if (string.IsNullOrEmpty (value)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (value)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs deleted file mode 100644 index c4250b82e231d..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkPublicAndFamilyAttribute.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SetupLinkerLinkPublicAndFamilyAttribute : BaseMetadataAttribute - { - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs deleted file mode 100644 index 5aa97e2ca05e2..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerLinkSymbolsAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class)] - public class SetupLinkerLinkSymbolsAttribute : BaseMetadataAttribute - { - public SetupLinkerLinkSymbolsAttribute (string value) - { - if (string.IsNullOrEmpty (value)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (value)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs deleted file mode 100644 index 28c30f868bcda..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerResponseFileAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupLinkerResponseFileAttribute : BaseMetadataAttribute - { - public SetupLinkerResponseFileAttribute (string relativePathToFile, string destinationFileName = null) - { - if (string.IsNullOrEmpty (relativePathToFile)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (relativePathToFile)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerSubstitutionFileAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerSubstitutionFileAttribute.cs deleted file mode 100644 index 6a102a830fa16..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerSubstitutionFileAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = true)] - public class SetupLinkerSubstitutionFileAttribute : BaseMetadataAttribute - { - public SetupLinkerSubstitutionFileAttribute (string relativePathToFile, string destinationFileName = null) - { - if (string.IsNullOrEmpty (relativePathToFile)) - throw new ArgumentException ("Value cannot be null or empty.", nameof (relativePathToFile)); - } - } -} \ No newline at end of file diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerTrimModeAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerTrimModeAttribute.cs deleted file mode 100644 index e303447291f56..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SetupLinkerTrimModeAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - [AttributeUsage (AttributeTargets.Class, AllowMultiple = false)] - public class SetupLinkerTrimModeAttribute : BaseMetadataAttribute - { - public SetupLinkerTrimModeAttribute (string action) - { - if (string.IsNullOrEmpty (action)) - throw new ArgumentNullException (nameof (action)); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs deleted file mode 100644 index 37fbce0e04cf1..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/SkipUnresolvedAttribute.cs +++ /dev/null @@ -1,15 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - public sealed class SkipUnresolvedAttribute : BaseMetadataAttribute - { - public readonly bool Value; - - public SkipUnresolvedAttribute (bool value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripDescriptorsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripDescriptorsAttribute.cs deleted file mode 100644 index 704d01971f3d5..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripDescriptorsAttribute.cs +++ /dev/null @@ -1,15 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - public sealed class StripDescriptorsAttribute : BaseMetadataAttribute - { - public readonly bool Value; - - public StripDescriptorsAttribute (bool value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripLinkAttributesAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripLinkAttributesAttribute.cs deleted file mode 100644 index 4f2380fb93884..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripLinkAttributesAttribute.cs +++ /dev/null @@ -1,15 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - public sealed class StripLinkAttributesAttribute : BaseMetadataAttribute - { - public readonly bool Value; - - public StripLinkAttributesAttribute (bool value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripSubstitutionsAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripSubstitutionsAttribute.cs deleted file mode 100644 index 1f0732216640f..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Metadata/StripSubstitutionsAttribute.cs +++ /dev/null @@ -1,15 +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. - -namespace Mono.Linker.Tests.Cases.Expectations.Metadata -{ - public sealed class StripSubstitutionsAttribute : BaseMetadataAttribute - { - public readonly bool Value; - - public StripSubstitutionsAttribute (bool value) - { - Value = value; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj deleted file mode 100644 index 14a94ab30bf27..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Mono.Linker.Tests.Cases.Expectations.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - $(NetCoreAppToolCurrent) - disable - x64;x86 - AnyCPU - - - diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/IntrinsicAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/IntrinsicAttribute.cs deleted file mode 100644 index 4c2153dbff35e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/IntrinsicAttribute.cs +++ /dev/null @@ -1,12 +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. - -namespace System.Runtime.CompilerServices -{ - // This attribute is normally implemented in CoreLib as internal, but in order to test - // linker behavior around it, we need to be able to use it in the tests. - [AttributeUsage (AttributeTargets.Method)] - public sealed class IntrinsicAttribute : Attribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/RemoveAttributeInstancesAttribute.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/RemoveAttributeInstancesAttribute.cs deleted file mode 100644 index e2eb936d545f8..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases.Expectations/Support/RemoveAttributeInstancesAttribute.cs +++ /dev/null @@ -1,17 +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; - -namespace Mono.Linker -{ - /// - /// This attribute name will be the name hardcoded in linker which will remove all - /// attribute usages but not the attribute definition - /// - [AttributeUsage ( - AttributeTargets.Class, Inherited = false)] - public sealed class RemoveAttributeInstancesAttribute : Attribute - { - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs deleted file mode 100644 index e2df9679801a4..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/AssemblyQualifiedNameDataflow.cs +++ /dev/null @@ -1,163 +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.CodeAnalysis; -using System.Text; -using Mono.Linker.Tests.Cases.Expectations.Assertions; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - // Note: this test's goal is to validate that the product correctly reports unrecognized patterns - // - so the main validation is done by the ExpectedWarning attributes. - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - class AssemblyQualifiedNameDataflow - { - static void Main () - { - TestPublicParameterlessConstructor (); - TestPublicConstructors (); - TestConstructors (); - TestUnqualifiedTypeNameWarns (); - TestNull (); - TestMultipleValues (); - TestUnknownValue (); - TestNoValue (); - TestObjectGetTypeValue (); - } - - [ExpectedWarning ("IL2072", nameof (RequirePublicConstructors))] - [ExpectedWarning ("IL2072", nameof (RequireNonPublicConstructors))] - static void TestPublicParameterlessConstructor () - { - string type = GetTypeWithPublicParameterlessConstructor ().AssemblyQualifiedName; - RequirePublicParameterlessConstructor (type); - RequirePublicConstructors (type); - RequireNonPublicConstructors (type); - RequireNothing (type); - } - - [ExpectedWarning ("IL2072", nameof (RequireNonPublicConstructors))] - static void TestPublicConstructors () - { - string type = GetTypeWithPublicConstructors ().AssemblyQualifiedName; - RequirePublicParameterlessConstructor (type); - RequirePublicConstructors (type); - RequireNonPublicConstructors (type); - RequireNothing (type); - } - - [ExpectedWarning ("IL2072", nameof (RequirePublicParameterlessConstructor))] - [ExpectedWarning ("IL2072", nameof (RequirePublicConstructors))] - static void TestConstructors () - { - string type = GetTypeWithNonPublicConstructors ().AssemblyQualifiedName; - RequirePublicParameterlessConstructor (type); - RequirePublicConstructors (type); - RequireNonPublicConstructors (type); - RequireNothing (type); - } - - [ExpectedWarning ("IL2105", - "Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " + - "Type name strings used for dynamically accessing a type should be assembly qualified.", - ProducedBy = ProducedBy.Trimmer)] - static void TestUnqualifiedTypeNameWarns () - { - RequirePublicConstructors ("System.Invalid.TypeName"); - } - - static void TestNull () - { - Type type = null; - RequirePublicConstructors (type.AssemblyQualifiedName); // Null should not warn - we know it's going to fail at runtime - } - - [ExpectedWarning ("IL2072", nameof (RequirePublicConstructors), nameof (GetTypeWithNonPublicConstructors))] - [ExpectedWarning ("IL2062", nameof (RequirePublicConstructors))] - static void TestMultipleValues (int p = 0, object[] o = null) - { - Type type = p switch { - 0 => GetTypeWithPublicConstructors (), - 1 => GetTypeWithNonPublicConstructors (), // Should produce warning IL2072 due to mismatch annotation - 2 => null, // Should be ignored - _ => (Type) o[0] // This creates an unknown value - should produce warning IL2062 - }; - - RequirePublicConstructors (type.AssemblyQualifiedName); - } - - [ExpectedWarning ("IL2062", nameof (RequirePublicConstructors))] - static void TestUnknownValue (object[] o = null) - { - string unknown = ((Type) o[0]).AssemblyQualifiedName; - RequirePublicConstructors (unknown); - RequireNothing (unknown); // shouldn't warn - } - - static void TestNoValue () - { - Type t = null; - Type noValue = Type.GetTypeFromHandle (t.TypeHandle); - // t.TypeHandle throws at runtime so don't warn here. - RequirePublicConstructors (noValue.AssemblyQualifiedName); - } - - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] - class AnnotatedType - { - } - - static void TestObjectGetTypeValue (AnnotatedType instance = null) - { - string type = instance.GetType ().AssemblyQualifiedName; - // Currently Object.GetType is unimplemented in the analyzer, but - // this still shouldn't warn. - RequirePublicConstructors (type); - RequireNothing (type); - } - - private static void RequirePublicParameterlessConstructor ( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] - string type) - { - } - - private static void RequirePublicConstructors ( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] - string type) - { - } - - private static void RequireNonPublicConstructors ( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] - string type) - { - } - - private static void RequireNothing (string type) - { - } - - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] - private static Type GetTypeWithPublicParameterlessConstructor () - { - return null; - } - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] - private static Type GetTypeWithPublicConstructors () - { - return null; - } - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] - private static Type GetTypeWithNonPublicConstructors () - { - return null; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/EmptyArrayIntrinsicsDataFlow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/EmptyArrayIntrinsicsDataFlow.cs deleted file mode 100644 index 268466a3b427d..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/EmptyArrayIntrinsicsDataFlow.cs +++ /dev/null @@ -1,60 +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.CodeAnalysis; -using System.Reflection; -using System.Text; -using Mono.Linker.Tests.Cases.Expectations.Assertions; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - // Note: this test's goal is to validate that the product correctly reports unrecognized patterns - // - so the main validation is done by the ExpectedWarning attributes. - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - class EmptyArrayIntrinsicsDataFlow - { - static void Main () - { - TestGetPublicParameterlessConstructorWithEmptyTypes (); - TestGetPublicParameterlessConstructorWithArrayEmpty (); - TestGetPublicParameterlessConstructorWithUnknownArray (); - TestGetConstructorOverloads (); - } - - [ExpectedWarning ("IL2080", nameof (Type.GetMethod))] - static void TestGetPublicParameterlessConstructorWithEmptyTypes () - { - s_typeWithKeptPublicParameterlessConstructor.GetConstructor (Type.EmptyTypes); - s_typeWithKeptPublicParameterlessConstructor.GetMethod ("Foo"); - } - - [ExpectedWarning ("IL2080", nameof (Type.GetMethod))] - static void TestGetPublicParameterlessConstructorWithArrayEmpty () - { - s_typeWithKeptPublicParameterlessConstructor.GetConstructor (Array.Empty ()); - s_typeWithKeptPublicParameterlessConstructor.GetMethod ("Foo"); - } - - [ExpectedWarning ("IL2080", nameof (Type.GetConstructor))] - static void TestGetPublicParameterlessConstructorWithUnknownArray () - { - s_typeWithKeptPublicParameterlessConstructor.GetConstructor (s_localEmptyArrayInvisibleToAnalysis); - } - - [ExpectedWarning ("IL2080", nameof (Type.GetMethod))] - static void TestGetConstructorOverloads () - { - s_typeWithKeptPublicParameterlessConstructor.GetConstructor (BindingFlags.Public, null, Type.EmptyTypes, null); - s_typeWithKeptPublicParameterlessConstructor.GetConstructor (BindingFlags.Public, null, CallingConventions.Any, Type.EmptyTypes, null); - s_typeWithKeptPublicParameterlessConstructor.GetMethod ("Foo"); - } - - static Type[] s_localEmptyArrayInvisibleToAnalysis = Type.EmptyTypes; - - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] - static Type s_typeWithKeptPublicParameterlessConstructor = typeof (EmptyArrayIntrinsicsDataFlow); - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs deleted file mode 100644 index a369157dbbc82..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetInterfaceDataFlow.cs +++ /dev/null @@ -1,198 +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.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - public class GetInterfaceDataFlow - { - public static void Main () - { - GetInterface_Name.Test (); - GetInterface_Name_IgnoreCase.Test (); - } - - class GetInterface_Name - { - static void TestNullName (Type type) - { - type.GetInterface (null); - } - - static void TestEmptyName (Type type) - { - type.GetInterface (string.Empty); - } - - static void TestNoValueName (Type type) - { - Type t = null; - string noValue = t.AssemblyQualifiedName; - type.GetInterface (noValue); - } - - [ExpectedWarning ("IL2070", nameof (Type.GetInterface), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] - static void TestNoAnnotation (Type type) - { - type.GetInterface ("ITestInterface"); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestWithAnnotation ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] Type type) - { - type.GetInterface ("ITestInterface").RequiresInterfaces (); - type.GetInterface ("ITestInterface").RequiresAll (); // Warns - } - - static void TestWithAll ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type type) - { - type.GetInterface ("ITestInterface").RequiresInterfaces (); - type.GetInterface ("ITestInterface").RequiresAll (); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestKnownType () - { - // Interfaces marking is transitive - meaning that it marks all interfaces in the entire hierarchy - // so the return value of GetInterface always has all interfaces on it already. - typeof (TestType).GetInterface ("ITestInterface").RequiresInterfaces (); - typeof (TestType).GetInterface ("ITestInterface").RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestMultipleValues (int p, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeWithAll) - { - Type type; - if (p == 0) - type = typeof (TestType); - else - type = typeWithAll; - - type.GetInterface ("ITestInterface").RequiresInterfaces (); - type.GetInterface ("ITestInterface").RequiresAll (); // Warns since only one of the values is guaranteed All - } - - [ExpectedWarning ("IL2075", nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] - static void TestMergedValues (int p, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeWithAll) - { - Type type = new TestType ().GetType (); - if (p == 0) { - type = typeWithAll; - } - - type.GetInterface ("ITestInterface").RequiresInterfaces (); - } - - static void TestNullValue () - { - Type t = null; - t.GetInterface ("ITestInterface").RequiresInterfaces (); - } - - static void TestNoValue () - { - Type t = null; - Type noValue = Type.GetTypeFromHandle (t.TypeHandle); - // t.TypeHandle throws at runtime so don't warn here. - noValue.GetInterface ("ITestInterface").RequiresInterfaces (); - } - - class GetInterfaceInCtor - { - public GetInterfaceInCtor ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] Type type) - { - type.GetInterface ("ITestInterface").RequiresInterfaces (); - } - } - - public static void Test () - { - TestNullName (typeof (TestType)); - TestEmptyName (typeof (TestType)); - TestNoValueName (typeof (TestType)); - TestNoAnnotation (typeof (TestType)); - TestWithAnnotation (typeof (TestType)); - TestWithAnnotation (typeof (ITestInterface)); - TestWithAll (typeof (TestType)); - TestKnownType (); - TestMultipleValues (0, typeof (TestType)); - TestMergedValues (0, typeof (TestType)); - TestNullValue (); - TestNoValue (); - var _ = new GetInterfaceInCtor (typeof (TestType)); - } - } - - class GetInterface_Name_IgnoreCase - { - [ExpectedWarning ("IL2070", nameof (Type.GetInterface), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] - static void TestNoAnnotation (Type type) - { - type.GetInterface ("ITestInterface", false); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestWithAnnotation ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] Type type) - { - type.GetInterface ("ITestInterface", false).RequiresInterfaces (); - type.GetInterface ("ITestInterface", false).RequiresAll (); // Warns - } - - static void TestWithAll ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type type) - { - type.GetInterface ("ITestInterface", false).RequiresInterfaces (); - type.GetInterface ("ITestInterface", false).RequiresAll (); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestKnownType () - { - // Interfaces marking is transitive - meaning that it marks all interfaces in the entire hierarchy - // so the return value of GetInterface always has all interfaces on it already. - typeof (TestType).GetInterface ("ITestInterface", false).RequiresInterfaces (); - typeof (TestType).GetInterface ("ITestInterface", false).RequiresAll (); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestMultipleValues (int p, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type typeWithAll) - { - Type type; - if (p == 0) - type = typeof (TestType); - else - type = typeWithAll; - - type.GetInterface ("ITestInterface", false).RequiresInterfaces (); - type.GetInterface ("ITestInterface", false).RequiresAll (); // Warns since only one of the values is guaranteed All - } - - public static void Test () - { - TestNoAnnotation (typeof (TestType)); - TestWithAnnotation (typeof (TestType)); - TestWithAnnotation (typeof (ITestInterface)); - TestWithAll (typeof (TestType)); - TestKnownType (); - TestMultipleValues (0, typeof (TestType)); - } - } - - interface ITestInterface - { - } - - class TestType : ITestInterface - { - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs deleted file mode 100644 index d8f14b71eb70f..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetNestedTypeOnAllAnnotatedType.cs +++ /dev/null @@ -1,141 +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.CodeAnalysis; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - [ExpectedNoWarnings] - [SkipKeptItemsValidation] - class GetNestedTypeOnAllAnnotatedType - { - static void Main () - { - TestOnAllAnnotatedParameter (typeof (TestType)); - TestOnNonAllAnnotatedParameter (typeof (TestType)); - TestWithBindingFlags (typeof (TestType)); - TestWithUnknownBindingFlags (BindingFlags.Public, typeof (TestType)); - TestUnsupportedBindingFlags (typeof (TestType)); - TestWithNull (); - TestWithEmptyInput (); - TestIfElse (1, typeof (TestType), typeof (TestType)); - TestSwitchAllValid (1, typeof (TestType)); - TestOnKnownTypeOnly (); - TestOnKnownTypeWithNullName (); - TestOnKnownTypeWithUnknownName ("noname"); - TestWithKnownTypeAndNameWhichDoesntExist (); - } - - static void TestOnAllAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentType) - { - var nestedType = parentType.GetNestedType (nameof (TestType.NestedType)); - nestedType.RequiresAll (); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] - static void TestOnNonAllAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicNestedTypes)] Type parentType) - { - var nestedType = parentType.GetNestedType (nameof (TestType.NestedType)); - nestedType.RequiresAll (); - } - - static void TestWithBindingFlags ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentType) - { - var nestedType = parentType.GetNestedType (nameof (TestType.NestedType), BindingFlags.Public); - nestedType.RequiresAll (); - } - - static void TestWithUnknownBindingFlags (BindingFlags bindingFlags, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentType) - { - var nestedType = parentType.GetNestedType (nameof (TestType.NestedType), bindingFlags); - nestedType.RequiresAll (); - } - - static void TestUnsupportedBindingFlags ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentType) - { - var nestedType = parentType.GetNestedType (nameof (TestType.NestedType), BindingFlags.IgnoreCase); - nestedType.RequiresAll (); - } - - static void TestWithNull () - { - Type parentType = null; - var nestedType = parentType.GetNestedType (nameof (TestType.NestedType)); - nestedType.RequiresAll (); - } - - static void TestWithEmptyInput () - { - Type t = null; - Type noValue = Type.GetTypeFromHandle (t.TypeHandle); // Throws at runtime -> tracked as empty value set - noValue.GetNestedType (nameof (TestType.NestedType)).RequiresAll (); // No warning - empty input - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] - static void TestIfElse (int number, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentWithAll, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicNestedTypes)] Type parentWithoutAll) - { - Type typeOfParent; - if (number == 1) { - typeOfParent = parentWithAll; - } else { - typeOfParent = parentWithoutAll; - } - var nestedType = typeOfParent.GetNestedType (nameof (TestType.NestedType)); - nestedType.RequiresAll (); - } - - static void TestSwitchAllValid (int number, [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type parentWithAll) - { - Type typeOfParent = number switch { - 1 => parentWithAll, - 2 => null, - 3 => typeof (TestType) - }; - - var nestedType = typeOfParent.GetNestedType (nameof (TestType.NestedType)); - nestedType.RequiresAll (); - } - - static void TestOnKnownTypeOnly () - { - typeof (TestType).GetNestedType (nameof (TestType.NestedType)).RequiresAll (); - } - - static void TestOnKnownTypeWithNullName () - { - typeof (TestType).GetNestedType (null).RequiresAll (); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresAll))] - static void TestOnKnownTypeWithUnknownName (string name) - { - // WARN - we will preserve the nested type, but not as a whole, just the type itself, so it can't fullfil the All annotation - typeof (TestType).GetNestedType (name).RequiresAll (); - } - - static void TestWithKnownTypeAndNameWhichDoesntExist () - { - // Should not warn since we can statically determine that GetNestedType will return null so there's no problem with trimming - typeof (TestType).GetNestedType ("NonExisting").RequiresAll (); - } - - class TestType - { - public class NestedType - { - NestedType () { } - public static int PublicStaticInt; - public void Method () { } - int Prop { get; set; } - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs deleted file mode 100644 index ef58eac310f4f..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeDataFlow.cs +++ /dev/null @@ -1,220 +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.CodeAnalysis; -using System.Text; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - // Note: this test's goal is to validate that the product correctly reports unrecognized patterns - // - so the main validation is done by the ExpectedWarning attributes. - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - public class GetTypeDataFlow - { - public static void Main () - { - TestPublicParameterlessConstructor (); - TestPublicConstructors (); - TestConstructors (); - TestNull (); - TestNoValue (); - TestUnknownType (); - - TestTypeNameFromParameter (null); - TestTypeNameFromField (); - - TestMultipleConstantValues (); - TestMultipleMixedValues (); - - TestStringEmpty (); - - TypeWithWarnings.Test (); - OverConstTypeName.Test (); - - // TODO: - // Test multi-value returns - // Type.GetType over a constant and a param - // Type.GetType over two params - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors))] - static void TestPublicParameterlessConstructor () - { - Type type = Type.GetType (GetStringTypeWithPublicParameterlessConstructor ()); - type.RequiresPublicParameterlessConstructor (); - type.RequiresPublicConstructors (); - type.RequiresNonPublicConstructors (); - type.RequiresNone (); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors))] - static void TestPublicConstructors () - { - Type type = Type.GetType (GetStringTypeWithPublicConstructors ()); - type.RequiresPublicParameterlessConstructor (); - type.RequiresPublicConstructors (); - type.RequiresNonPublicConstructors (); - type.RequiresNone (); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicParameterlessConstructor))] - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - static void TestConstructors () - { - Type type = Type.GetType (GetStringTypeWithNonPublicConstructors ()); - type.RequiresPublicParameterlessConstructor (); - type.RequiresPublicConstructors (); - type.RequiresNonPublicConstructors (); - type.RequiresNone (); - } - - static void TestNull () - { - // GetType(null) throws at runtime, so we "give up" on analysis - Type.GetType (null).RequiresAll (); - } - - static void TestNoValue () - { - Type t = null; - // null.AssemblyQualifiedName throws at runtime, so we "give up" on analysis - string noValue = t.AssemblyQualifiedName; - Type.GetType (noValue).RequiresAll (); - } - - [ExpectedWarning ("IL2057", nameof (GetType))] - static void TestUnknownType () - { - Type type = Type.GetType (GetStringUnkownType ()); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - static void TestTypeNameFromParameter ( - [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] - string typeName) - { - Type.GetType (typeName).RequiresPublicConstructors (); - } - - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] - static string _typeNameWithPublicParameterlessConstructor; - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresPublicConstructors))] - static void TestTypeNameFromField () - { - Type.GetType (_typeNameWithPublicParameterlessConstructor).RequiresPublicConstructors (); - } - - static int _switchOnField; - - static void TestMultipleConstantValues () - { - string typeName = null; - switch (_switchOnField) { - case 0: // valid - typeName = "Mono.Linker.Tests.Cases.DataFlow.GetTypeDataFlow"; - break; - case 1: // null - typeName = null; - break; - case 2: // invalid - typeName = "UnknownType"; - break; - case 3: // invalid second - typeName = "AnotherUnknownType"; - break; - } - - Type.GetType (typeName); - } - - static void TestStringEmpty () - { - Type.GetType (string.Empty); - } - - [ExpectedWarning ("IL2072", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (Type.GetType))] - [ExpectedWarning ("IL2057", "System.Type.GetType(String)")] - static void TestMultipleMixedValues () - { - string typeName = null; - switch (_switchOnField) { - case 0: - typeName = GetStringTypeWithPublicParameterlessConstructor (); - break; - case 1: - typeName = GetStringTypeWithNonPublicConstructors (); - break; - case 2: - typeName = "Mono.Linker.Tests.Cases.DataFlow.GetTypeDataFlow"; - break; - case 3: - typeName = GetStringUnkownType (); - break; - } - - Type.GetType (typeName).RequiresNonPublicConstructors (); - } - - class TypeWithWarnings - { - [RequiresUnreferencedCode ("--Method1--")] - public void Method1 () { } - - [RequiresUnreferencedCode ("--Method2--")] - public void Method2 () { } - - // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--Method1--", ProducedBy = ProducedBy.Trimmer)] - [ExpectedWarning ("IL2026", "--Method2--", ProducedBy = ProducedBy.Trimmer)] - public static void Test () - { - Type.GetType ("Mono.Linker.Tests.Cases.DataFlow." + nameof (GetTypeDataFlow) + "+" + nameof (TypeWithWarnings)).RequiresPublicMethods (); - } - } - - class OverConstTypeName - { - private const string s_ConstTypeName = "Mono.Linker.Tests.Cases.DataFlow." + nameof (GetTypeDataFlow) + "+" + nameof (OverConstTypeName); - - [RequiresUnreferencedCode ("--Method1--")] - public void Method1 () { } - - // https://github.com/dotnet/linker/issues/2273 - [ExpectedWarning ("IL2026", "--Method1--", ProducedBy = ProducedBy.Trimmer)] - public static void Test () - { - Type.GetType (s_ConstTypeName).RequiresPublicMethods (); - } - } - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] - private static string GetStringTypeWithPublicParameterlessConstructor () - { - return null; - } - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] - private static string GetStringTypeWithPublicConstructors () - { - return null; - } - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] - private static string GetStringTypeWithNonPublicConstructors () - { - return null; - } - - private static string GetStringUnkownType () - { - return null; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeInfoDataFlow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeInfoDataFlow.cs deleted file mode 100644 index 29c25403e615b..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/GetTypeInfoDataFlow.cs +++ /dev/null @@ -1,54 +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.Diagnostics.CodeAnalysis; -using System.Reflection; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - class GetTypeInfoDataFlow - { - public static void Main () - { - TestNoAnnotations (typeof (TestType)); - TestWithAnnotations (typeof (TestType)); - TestWithNull (); - TestWithNoValue (); - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void TestNoAnnotations (Type t) - { - t.GetTypeInfo ().RequiresPublicMethods (); - t.GetTypeInfo ().RequiresNone (); - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - static void TestWithAnnotations ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type t) - { - t.GetTypeInfo ().RequiresPublicMethods (); - t.GetTypeInfo ().RequiresPublicFields (); - t.GetTypeInfo ().RequiresNone (); - } - - static void TestWithNull () - { - Type t = null; - t.GetTypeInfo ().RequiresPublicMethods (); - } - - static void TestWithNoValue () - { - Type t = null; - Type noValue = Type.GetTypeFromHandle (t.TypeHandle); - noValue.GetTypeInfo ().RequiresPublicMethods (); - } - - class TestType { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs deleted file mode 100644 index 7ae4a6ac5e8dd..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/MemberTypesRelationships.cs +++ /dev/null @@ -1,275 +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.CodeAnalysis; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - public class MemberTypesRelationships - { - public static void Main () - { - TestPublicParameterlessConstructor (typeof (TestType)); - TestPublicConstructors (typeof (TestType)); - TestNonPublicConstructors (typeof (TestType)); - TestPublicMethods (typeof (TestType)); - TestNonPublicMethods (typeof (TestType)); - TestPublicFields (typeof (TestType)); - TestNonPublicFields (typeof (TestType)); - TestPublicNestedTypes (typeof (TestType)); - TestNonPublicNestedTypes (typeof (TestType)); - TestPublicProperties (typeof (TestType)); - TestNonPublicProperties (typeof (TestType)); - TestPublicEvents (typeof (TestType)); - TestNonPublicEvents (typeof (TestType)); - TestInterfaces (typeof (TestType)); - TestAll (typeof (TestType)); - TestMultiple (typeof (TestType)); - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestPublicParameterlessConstructor ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type type) - { - type.RequiresPublicParameterlessConstructor (); - type.RequiresPublicConstructors (); // Warns - type.RequiresNonPublicConstructors (); // Warns - type.RequiresNone (); - type.RequiresPublicMethods (); // Warns - type.RequiresAll (); // Warns - } - - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestPublicConstructors ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) - { - type.RequiresPublicParameterlessConstructor (); - type.RequiresPublicConstructors (); - type.RequiresNonPublicConstructors (); // Warns - type.RequiresNone (); - type.RequiresPublicMethods (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicParameterlessConstructor), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestNonPublicConstructors ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type type) - { - type.RequiresPublicParameterlessConstructor (); // Warns - type.RequiresPublicConstructors (); // Warns - type.RequiresNonPublicConstructors (); - type.RequiresNone (); - type.RequiresPublicMethods (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), "y '" + nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors) + "' i")] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestPublicMethods ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) - { - type.RequiresPublicMethods (); - type.RequiresNonPublicMethods (); // Warns - type.RequiresNone (); - type.RequiresPublicConstructors (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicMethods))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestNonPublicMethods ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] Type type) - { - type.RequiresPublicMethods (); // Warns - type.RequiresNonPublicMethods (); - type.RequiresNone (); - type.RequiresNonPublicConstructors (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestPublicFields ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)] Type type) - { - type.RequiresPublicFields (); - type.RequiresNonPublicFields (); // Warns - type.RequiresNone (); - type.RequiresPublicConstructors (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicConstructors), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicConstructors))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestNonPublicFields ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicFields)] Type type) - { - type.RequiresPublicFields (); // Warns - type.RequiresNonPublicFields (); - type.RequiresNone (); - type.RequiresNonPublicConstructors (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresInterfaces), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestPublicNestedTypes ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicNestedTypes)] Type type) - { - type.RequiresPublicNestedTypes (); - type.RequiresNonPublicNestedTypes (); // Warns - type.RequiresNone (); - type.RequiresInterfaces (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresInterfaces), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestNonPublicNestedTypes ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] Type type) - { - type.RequiresPublicNestedTypes (); // Warns - type.RequiresNonPublicNestedTypes (); - type.RequiresNone (); - type.RequiresInterfaces (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicProperties), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicProperties))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestPublicProperties ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicProperties)] Type type) - { - type.RequiresPublicProperties (); - type.RequiresNonPublicProperties (); // Warns - type.RequiresNone (); - type.RequiresPublicFields (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicProperties), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicProperties))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestNonPublicProperties ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicProperties)] Type type) - { - type.RequiresPublicProperties (); // Warns - type.RequiresNonPublicProperties (); - type.RequiresNone (); - type.RequiresNonPublicFields (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicEvents), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicEvents))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestPublicEvents ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicEvents)] Type type) - { - type.RequiresPublicEvents (); - type.RequiresNonPublicEvents (); // Warns - type.RequiresNone (); - type.RequiresPublicFields (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicEvents), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicEvents))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicFields), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestNonPublicEvents ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicEvents)] Type type) - { - type.RequiresPublicEvents (); // Warns - type.RequiresNonPublicEvents (); - type.RequiresNone (); - type.RequiresNonPublicFields (); // Warns - type.RequiresAll (); // Warns - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.PublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresNonPublicNestedTypes), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicNestedTypes))] - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresAll), nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.All))] - static void TestInterfaces ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces)] Type type) - { - type.RequiresInterfaces (); - type.RequiresNone (); - type.RequiresPublicNestedTypes (); // Warns - type.RequiresNonPublicNestedTypes (); // Warns - type.RequiresAll (); // Warns - } - - static void TestAll ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] Type type) - { - type.RequiresAll (); - type.RequiresNone (); - type.RequiresPublicParameterlessConstructor (); - type.RequiresPublicConstructors (); - type.RequiresNonPublicConstructors (); - type.RequiresPublicMethods (); - type.RequiresNonPublicMethods (); - type.RequiresPublicFields (); - type.RequiresNonPublicFields (); - type.RequiresPublicNestedTypes (); - type.RequiresNonPublicNestedTypes (); - type.RequiresPublicProperties (); - type.RequiresNonPublicProperties (); - type.RequiresPublicEvents (); - type.RequiresNonPublicEvents (); - type.RequiresInterfaces (); - } - - static void RequiresMultiplePrivates ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods | DynamicallyAccessedMemberTypes.NonPublicFields)] Type type) - { - } - - static void RequiresSomePublic ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.Interfaces | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor | DynamicallyAccessedMemberTypes.NonPublicNestedTypes | DynamicallyAccessedMemberTypes.PublicMethods)] Type type) - { - } - - [ExpectedWarning ("IL2067", - nameof (RequiresMultiplePrivates), - nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicMethods), - nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicFields))] - [ExpectedWarning ("IL2067", - nameof (RequiresSomePublic), - nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.Interfaces), - nameof (DynamicallyAccessedMemberTypes) + "." + nameof (DynamicallyAccessedMemberTypes.NonPublicNestedTypes))] - static void TestMultiple ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicConstructors)] Type type) - { - RequiresMultiplePrivates (type); - RequiresSomePublic (type); - } - - class TestType { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/TypeInfoAsTypeDataFlow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/TypeInfoAsTypeDataFlow.cs deleted file mode 100644 index d14b101a9285c..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/TypeInfoAsTypeDataFlow.cs +++ /dev/null @@ -1,55 +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.Diagnostics.CodeAnalysis; -using System.Reflection; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - class TypeInfoAsTypeDataFlow - { - public static void Main () - { - TestNoAnnotations (typeof (TestType).GetTypeInfo ()); - TestWithAnnotations (typeof (TestType).GetTypeInfo ()); - TestWithNull (); - TestWithNoValue (); - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicMethods))] - static void TestNoAnnotations (TypeInfo t) - { - t.AsType ().RequiresPublicMethods (); - t.AsType ().RequiresNone (); - } - - [ExpectedWarning ("IL2067", nameof (DataFlowTypeExtensions.RequiresPublicFields))] - static void TestWithAnnotations ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] TypeInfo t) - { - t.AsType ().RequiresPublicMethods (); - t.AsType ().RequiresPublicFields (); - t.AsType ().RequiresNone (); - } - - static void TestWithNull () - { - TypeInfo t = null; - t.AsType ().RequiresPublicMethods (); - } - - static void TestWithNoValue () - { - Type t = null; - Type noValueType = Type.GetTypeFromHandle (t.TypeHandle); - TypeInfo noValue = noValueType.GetTypeInfo (); - noValue.AsType ().RequiresPublicMethods (); - } - - class TestType { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/UnsafeDataFlow.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/UnsafeDataFlow.cs deleted file mode 100644 index c4d9f98d58493..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/DataFlow/UnsafeDataFlow.cs +++ /dev/null @@ -1,68 +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.Diagnostics.CodeAnalysis; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; -using Mono.Linker.Tests.Cases.Expectations.Metadata; - -namespace Mono.Linker.Tests.Cases.DataFlow -{ - [SetupCompileArgument ("/unsafe")] - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - class UnsafeDataFlow - { - public static void Main () - { - TestReadFromPointer (); - TestWriteToPointer (); - TestWriteToStackAllocedStruct (); - } - - // We don't analyze the pointer manipulation, so it should produce a warning - // about reading an unknown type, without crashing the analyzer. - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))] - static unsafe void TestReadFromPointer () - { - int i = 6; - int* pI = &i; - Type[] arr = new Type[] { GetWithPublicMethods () }; - arr[*pI].RequiresAll (); - } - - // We don't analyze the pointer manipulation, so it should produce a warning - // about reading an unknown type, without crashing the analyzer. - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))] - static unsafe void TestWriteToPointer () - { - int i = 6; - int* pI = &i; - *pI = 0; - Type[] arr = new Type[] { GetWithPublicMethods () }; - arr[i].RequiresAll (); - } - - // We don't analyze the stackalloc'd struct member, so it should produce a warning - // about reading an unknown type, without crashing the analyzer. - [ExpectedWarning ("IL2062", nameof (DataFlowTypeExtensions.RequiresAll))] - static unsafe void TestWriteToStackAllocedStruct () - { - var stackArr = stackalloc S[1]; - stackArr[0] = new S { - I = 0 - }; - Type[] arr = new Type[] { GetWithPublicMethods () }; - arr[stackArr[0].I].RequiresAll (); - } - - struct S - { - public int I; - } - - [return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] - static Type GetWithPublicMethods () => null; - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj deleted file mode 100644 index ec237817f2901..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Mono.Linker.Tests.Cases.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - $(NetCoreAppToolCurrent) - x64;x86 - AnyCPU - true - $(DefineConstants);INCLUDE_EXPECTATIONS - 0 - 0 - - - - - - - diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Repro/Program.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Repro/Program.cs deleted file mode 100644 index 6aba1d869f9c1..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/Repro/Program.cs +++ /dev/null @@ -1,30 +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.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; -using Mono.Linker.Tests.Cases.Expectations.Metadata; - -namespace Mono.Linker.Tests.Cases.Repro -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - public class Program - { - - public static void Main () - { - Console.WriteLine ("HelloWorld"); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs b/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs deleted file mode 100644 index b89dfc61e8cf3..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests.Cases/RequiresCapability/BasicRequires.cs +++ /dev/null @@ -1,215 +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.Diagnostics.CodeAnalysis; -using System.IO; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Helpers; -using Mono.Linker.Tests.Cases.Expectations.Metadata; - -namespace Mono.Linker.Tests.Cases.RequiresCapability -{ - [SkipKeptItemsValidation] - [ExpectedNoWarnings] - public class BasicRequires - { - - public static void Main () - { - TestRequiresWithMessageOnlyOnMethod (); - TestRequiresWithMessageAndUrlOnMethod (); - TestRequiresOnConstructor (); - TestRequiresOnPropertyGetterAndSetter (); - TestThatTrailingPeriodIsAddedToMessage (); - TestThatTrailingPeriodIsNotDuplicatedInWarningMessage (); - TestRequiresFromNameOf (); - OnEventMethod.Test (); - RequiresOnGenerics.Test (); - } - - [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageOnly--.")] - [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageOnly--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageOnly--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - static void TestRequiresWithMessageOnlyOnMethod () - { - RequiresWithMessageOnly (); - } - - [RequiresUnreferencedCode ("Message for --RequiresWithMessageOnly--")] - [RequiresAssemblyFiles ("Message for --RequiresWithMessageOnly--")] - [RequiresDynamicCode ("Message for --RequiresWithMessageOnly--")] - static void RequiresWithMessageOnly () - { - } - - [ExpectedWarning ("IL2026", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl")] - [ExpectedWarning ("IL3002", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --RequiresWithMessageAndUrl--.", "https://helpurl", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - static void TestRequiresWithMessageAndUrlOnMethod () - { - RequiresWithMessageAndUrl (); - } - - [RequiresUnreferencedCode ("Message for --RequiresWithMessageAndUrl--", Url = "https://helpurl")] - [RequiresAssemblyFiles ("Message for --RequiresWithMessageAndUrl--", Url = "https://helpurl")] - [RequiresDynamicCode ("Message for --RequiresWithMessageAndUrl--", Url = "https://helpurl")] - static void RequiresWithMessageAndUrl () - { - } - - [ExpectedWarning ("IL2026", "Message for --ConstructorRequires--.")] - [ExpectedWarning ("IL3002", "Message for --ConstructorRequires--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --ConstructorRequires--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - static void TestRequiresOnConstructor () - { - new ConstructorRequires (); - } - - class ConstructorRequires - { - [RequiresUnreferencedCode ("Message for --ConstructorRequires--")] - [RequiresAssemblyFiles ("Message for --ConstructorRequires--")] - [RequiresDynamicCode ("Message for --ConstructorRequires--")] - public ConstructorRequires () - { - } - } - - [ExpectedWarning ("IL2026", "Message for --getter PropertyRequires--.")] - [ExpectedWarning ("IL2026", "Message for --setter PropertyRequires--.")] - [ExpectedWarning ("IL3002", "Message for --getter PropertyRequires--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3002", "Message for --setter PropertyRequires--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --getter PropertyRequires--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "Message for --setter PropertyRequires--.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - static void TestRequiresOnPropertyGetterAndSetter () - { - _ = PropertyRequires; - PropertyRequires = 0; - } - - static int PropertyRequires { - [RequiresUnreferencedCode ("Message for --getter PropertyRequires--")] - [RequiresAssemblyFiles ("Message for --getter PropertyRequires--")] - [RequiresDynamicCode ("Message for --getter PropertyRequires--")] - get { return 42; } - - [RequiresUnreferencedCode ("Message for --setter PropertyRequires--")] - [RequiresAssemblyFiles ("Message for --setter PropertyRequires--")] - [RequiresDynamicCode ("Message for --setter PropertyRequires--")] - set { } - } - - [RequiresUnreferencedCode ("Linker adds a trailing period to this message")] - [RequiresAssemblyFiles ("Linker adds a trailing period to this message")] - [RequiresDynamicCode ("Linker adds a trailing period to this message")] - static void WarningMessageWithoutEndingPeriod () - { - } - - [ExpectedWarning ("IL2026", "Linker adds a trailing period to this message.")] - [ExpectedWarning ("IL3002", "Linker adds a trailing period to this message.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "Linker adds a trailing period to this message.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - static void TestThatTrailingPeriodIsAddedToMessage () - { - WarningMessageWithoutEndingPeriod (); - } - - [RequiresUnreferencedCode ("Linker does not add a period to this message.")] - [RequiresAssemblyFiles ("Linker does not add a period to this message.")] - [RequiresDynamicCode ("Linker does not add a period to this message.")] - static void WarningMessageEndsWithPeriod () - { - } - - [LogDoesNotContain ("Linker does not add a period to this message..")] - [ExpectedWarning ("IL2026", "Linker does not add a period to this message.")] - [ExpectedWarning ("IL3002", "Linker does not add a period to this message.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "Linker does not add a period to this message.", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - static void TestThatTrailingPeriodIsNotDuplicatedInWarningMessage () - { - WarningMessageEndsWithPeriod (); - } - - static void TestRequiresFromNameOf () - { - _ = nameof (BasicRequires.RequiresWithMessageOnly); - } - - class OnEventMethod - { - [ExpectedWarning ("IL2026", "--EventToTestRemove.remove--", ProducedBy = ProducedBy.Trimmer)] - [ExpectedWarning ("IL2026", "--EventToTestRemove.remove--", ProducedBy = ProducedBy.Trimmer)] - static event EventHandler EventToTestRemove { - add { } - [RequiresUnreferencedCode ("Message for --EventToTestRemove.remove--")] - [RequiresAssemblyFiles ("Message for --EventToTestRemove.remove--")] - [RequiresDynamicCode ("Message for --EventToTestRemove.remove--")] - remove { } - } - - [ExpectedWarning ("IL2026", "--EventToTestAdd.add--", ProducedBy = ProducedBy.Trimmer)] - [ExpectedWarning ("IL2026", "--EventToTestAdd.add--", ProducedBy = ProducedBy.Trimmer)] - static event EventHandler EventToTestAdd { - [RequiresUnreferencedCode ("Message for --EventToTestAdd.add--")] - [RequiresAssemblyFiles ("Message for --EventToTestAdd.add--")] - [RequiresDynamicCode ("Message for --EventToTestAdd.add--")] - add { } - remove { } - } - - [ExpectedWarning ("IL2026", "--EventToTestRemove.remove--")] - [ExpectedWarning ("IL3002", "--EventToTestRemove.remove--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "--EventToTestRemove.remove--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL2026", "--EventToTestAdd.add--")] - [ExpectedWarning ("IL3002", "--EventToTestAdd.add--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "--EventToTestAdd.add--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - public static void Test () - { - EventToTestRemove -= (sender, e) => { }; - EventToTestAdd += (sender, e) => { }; - } - } - - class RequiresOnGenerics - { - class GenericWithStaticMethod - { - [RequiresUnreferencedCode ("Message for --GenericTypeWithStaticMethodWhichRequires--")] - [RequiresAssemblyFiles ("Message for --GenericTypeWithStaticMethodWhichRequires--")] - [RequiresDynamicCode ("Message for --GenericTypeWithStaticMethodWhichRequires--")] - public static void GenericTypeWithStaticMethodWhichRequires () { } - } - - // NativeAOT doesnt produce Requires warnings in Generics https://github.com/dotnet/runtime/issues/68688 - // [ExpectedWarning("IL2026", "--GenericTypeWithStaticMethodWhichRequires--"] - [ExpectedWarning ("IL2026", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.Trimmer)] - // [ExpectedWarning("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3002", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer)] - // [ExpectedWarning("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer | ProducedBy.NativeAot)] - [ExpectedWarning ("IL3050", "--GenericTypeWithStaticMethodWhichRequires--", ProducedBy = ProducedBy.Analyzer)] - public static void GenericTypeWithStaticMethodViaLdftn () - { - var _ = new Action (GenericWithStaticMethod.GenericTypeWithStaticMethodWhichRequires); - } - - class TestType { } - - static T MakeNew () where T : new() => new T (); - static T MakeNew2 () where T : new() => MakeNew (); - - public static void Test () - { - GenericTypeWithStaticMethodViaLdftn (); - MakeNew2 (); - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/CecilExtensions.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/CecilExtensions.cs deleted file mode 100644 index afcefb9380488..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/CecilExtensions.cs +++ /dev/null @@ -1,368 +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.Linq; -using System.Text; -using Mono.Cecil; - -namespace Mono.Linker.Tests.Extensions -{ - public static class CecilExtensions - { - public static IEnumerable AllDefinedTypes (this AssemblyDefinition assemblyDefinition) - { - return assemblyDefinition.Modules.SelectMany (m => m.AllDefinedTypes ()); - } - - public static IEnumerable AllDefinedTypes (this ModuleDefinition moduleDefinition) - { - foreach (var typeDefinition in moduleDefinition.Types) { - yield return typeDefinition; - - foreach (var definition in typeDefinition.AllDefinedTypes ()) - yield return definition; - } - } - - public static IEnumerable AllDefinedTypes (this TypeDefinition typeDefinition) - { - foreach (var nestedType in typeDefinition.NestedTypes) { - yield return nestedType; - - foreach (var definition in nestedType.AllDefinedTypes ()) - yield return definition; - } - } - - public static IEnumerable AllMembers (this ModuleDefinition module) - { - foreach (var type in module.AllDefinedTypes ()) { - yield return type; - - foreach (var member in type.AllMembers ()) - yield return member; - } - } - - public static IEnumerable AllMembers (this TypeDefinition type) - { - foreach (var field in type.Fields) - yield return field; - - foreach (var prop in type.Properties) - yield return prop; - - foreach (var method in type.Methods) - yield return method; - - foreach (var @event in type.Events) - yield return @event; - } - - public static IEnumerable AllMethods (this TypeDefinition type) - { - foreach (var m in type.AllMembers ()) { - switch (m) { - case MethodDefinition method: - yield return method; - break; - case PropertyDefinition @property: - if (@property.GetMethod != null) - yield return @property.GetMethod; - - if (@property.SetMethod != null) - yield return @property.SetMethod; - - break; - case EventDefinition @event: - if (@event.AddMethod != null) - yield return @event.AddMethod; - - if (@event.RemoveMethod != null) - yield return @event.RemoveMethod; - - break; - - default: - break; - } - } - } - - public static bool HasAttribute (this ICustomAttributeProvider provider, string name) - { - return provider.CustomAttributes.Any (ca => ca.AttributeType.Name == name); - } - - public static bool HasAttributeDerivedFrom (this ICustomAttributeProvider provider, string name) - { - return provider.CustomAttributes.Any (ca => ca.AttributeType.Resolve ().DerivesFrom (name)); - } - - public static bool DerivesFrom (this TypeDefinition type, string baseTypeName) - { - if (type.Name == baseTypeName) - return true; - - if (type.BaseType == null) - return false; - - if (type.BaseType.Name == baseTypeName) - return true; - - return type.BaseType.Resolve ()?.DerivesFrom (baseTypeName) ?? false; - } - - public static PropertyDefinition GetPropertyDefinition (this MethodDefinition method) - { - if (!method.IsSetter && !method.IsGetter) - throw new ArgumentException (); - - var propertyName = method.Name.Substring (4); - return method.DeclaringType.Properties.First (p => p.Name == propertyName); - } - - public static string GetSignature (this MethodDefinition method) - { - var builder = new StringBuilder (); - builder.Append (method.Name); - if (method.HasGenericParameters) { - builder.Append ($"<#{method.GenericParameters.Count}>"); - } - - builder.Append ("("); - - if (method.HasParameters) { - for (int i = 0; i < method.Parameters.Count - 1; i++) { - // TODO: modifiers - // TODO: default values - builder.Append ($"{method.Parameters[i].ParameterType},"); - } - - builder.Append (method.Parameters[method.Parameters.Count - 1].ParameterType); - } - - builder.Append (")"); - - return builder.ToString (); - } - - public static object GetConstructorArgumentValue (this CustomAttribute attr, int argumentIndex) - { - return attr.ConstructorArguments[argumentIndex].Value; - } - - public static object? GetPropertyValue (this CustomAttribute attr, string propertyName) - { - foreach (var prop in attr.Properties) - if (prop.Name == propertyName) - return prop.Argument.Value; - - return null; - } - - public static bool IsEventMethod(this MethodDefinition md) - { - return (md.SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0 || - (md.SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0 || - (md.SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0; - } - - public static string GetDisplayName(this MethodReference method) - { - var sb = new System.Text.StringBuilder(); - - // Match C# syntaxis name if setter or getter - var methodDefinition = method.Resolve(); - if (methodDefinition != null && (methodDefinition.IsSetter || methodDefinition.IsGetter)) - { - // Append property name - string name = methodDefinition.IsSetter ? string.Concat(methodDefinition.Name.AsSpan(4), ".set") : string.Concat(methodDefinition.Name.AsSpan(4), ".get"); - sb.Append(name); - // Insert declaring type name and namespace - sb.Insert(0, '.').Insert(0, method.DeclaringType?.GetDisplayName()); - return sb.ToString(); - } - - if (methodDefinition != null && methodDefinition.IsEventMethod()) - { - // Append event name - string name = methodDefinition.SemanticsAttributes switch - { - MethodSemanticsAttributes.AddOn => string.Concat(methodDefinition.Name.AsSpan(4), ".add"), - MethodSemanticsAttributes.RemoveOn => string.Concat(methodDefinition.Name.AsSpan(7), ".remove"), - MethodSemanticsAttributes.Fire => string.Concat(methodDefinition.Name.AsSpan(6), ".raise"), - _ => throw new NotSupportedException(), - }; - sb.Append(name); - // Insert declaring type name and namespace - sb.Insert(0, '.').Insert(0, method.DeclaringType.GetDisplayName()); - return sb.ToString(); - } - - // Append parameters - sb.Append("("); - if (method.HasParameters) - { - for (int i = 0; i < method.Parameters.Count - 1; i++) - sb.Append(method.Parameters[i].ParameterType.GetDisplayNameWithoutNamespace()).Append(", "); - - sb.Append(method.Parameters[method.Parameters.Count - 1].ParameterType.GetDisplayNameWithoutNamespace()); - } - - sb.Append(")"); - - // Insert generic parameters - if (method.HasGenericParameters) - { - PrependGenericParameters(method.GenericParameters, sb); - } - - // Insert method name - if (method.Name == ".ctor") - sb.Insert(0, method.DeclaringType.Name); - else - sb.Insert(0, method.Name); - - // Insert declaring type name and namespace - if (method.DeclaringType != null) - sb.Insert(0, '.').Insert(0, method.DeclaringType.GetDisplayName()); - - return sb.ToString(); - } - - public static string GetDisplayName(this TypeReference type) - { - var builder = GetDisplayNameWithoutNamespace(type); - var namespaceDisplayName = type.GetNamespaceDisplayName(); - if (!string.IsNullOrEmpty(namespaceDisplayName)) - { - builder.Insert(0, "."); - builder.Insert(0, namespaceDisplayName); - } - - return builder.ToString(); - } - - public static string GetDisplayName(this FieldReference field) - { - var builder = new StringBuilder(); - if (field.DeclaringType != null) - { - builder.Append(field.DeclaringType.GetDisplayName()); - builder.Append("."); - } - - builder.Append(field.Name); - - return builder.ToString(); - } - - public static string GetNamespaceDisplayName(this MemberReference member) - { - var type = member is TypeReference typeReference ? typeReference : member.DeclaringType; - while (type.DeclaringType != null) - type = type.DeclaringType; - - return type.Namespace; - } - - public static StringBuilder GetDisplayNameWithoutNamespace(this TypeReference type) - { - var sb = new StringBuilder(); - if (type == null) - return sb; - - Stack? genericArguments = null; - while (true) - { - switch (type) - { - case ArrayType arrayType: - AppendArrayType(arrayType, sb); - break; - case GenericInstanceType genericInstanceType: - genericArguments = new Stack(genericInstanceType.GenericArguments); - type = genericInstanceType.ElementType; - continue; - default: - if (type.HasGenericParameters) - { - int genericParametersCount = type.GenericParameters.Count; - int declaringTypeGenericParametersCount = type.DeclaringType?.GenericParameters?.Count ?? 0; - - string simpleName; - if (genericParametersCount > declaringTypeGenericParametersCount) - { - if (genericArguments?.Count > 0) - PrependGenericArguments(genericArguments, genericParametersCount - declaringTypeGenericParametersCount, sb); - else - PrependGenericParameters(type.GenericParameters.Skip(declaringTypeGenericParametersCount).ToList(), sb); - - int explicitArityIndex = type.Name.IndexOf('`'); - simpleName = explicitArityIndex != -1 ? type.Name.Substring(0, explicitArityIndex) : type.Name; - } - else - simpleName = type.Name; - - sb.Insert(0, simpleName); - break; - } - - sb.Insert(0, type.Name); - break; - } - - if (type.DeclaringType is not TypeReference declaringType) - break; - - type = declaringType; - - sb.Insert(0, '.'); - } - - return sb; - } - - public static void PrependGenericParameters(IList genericParameters, StringBuilder sb) - { - sb.Insert(0, '>').Insert(0, genericParameters[genericParameters.Count - 1]); - for (int i = genericParameters.Count - 2; i >= 0; i--) - sb.Insert(0, ',').Insert(0, genericParameters[i]); - - sb.Insert(0, '<'); - } - - static void PrependGenericArguments(Stack genericArguments, int argumentsToTake, StringBuilder sb) - { - sb.Insert(0, '>').Insert(0, genericArguments.Pop().GetDisplayNameWithoutNamespace().ToString()); - while (--argumentsToTake > 0) - sb.Insert(0, ',').Insert(0, genericArguments.Pop().GetDisplayNameWithoutNamespace().ToString()); - - sb.Insert(0, '<'); - } - - static void AppendArrayType(ArrayType arrayType, StringBuilder sb) - { - void parseArrayDimensions(ArrayType at) - { - sb.Append('['); - for (int i = 0; i < at.Dimensions.Count - 1; i++) - sb.Append(','); - - sb.Append(']'); - } - - sb.Append(arrayType.Name.AsSpan(0, arrayType.Name.IndexOf('['))); - parseArrayDimensions(arrayType); - var element = arrayType.ElementType as ArrayType; - while (element != null) - { - parseArrayDimensions(element); - element = element.ElementType as ArrayType; - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/NiceIO.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/NiceIO.cs deleted file mode 100644 index 9272ffc026c03..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/Extensions/NiceIO.cs +++ /dev/null @@ -1,864 +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. - -// The MIT License(MIT) -// ===================== -// -// Copyright © `2015-2017` `Lucas Meijer` -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace Mono.Linker.Tests.Extensions -{ - public class NPath : IEquatable, IComparable - { - private static readonly StringComparison PathStringComparison = IsLinux () ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; - - private readonly string[] _elements; - private readonly bool _isRelative; - private readonly string? _driveLetter; - - #region construction - - public NPath (string path) - { - if (path == null) - throw new ArgumentNullException (); - - path = ParseDriveLetter (path, out _driveLetter); - - if (path == "/") { - _isRelative = false; - _elements = new string[] { }; - } else { - var split = path.Split ('/', '\\'); - - _isRelative = _driveLetter == null && IsRelativeFromSplitString (split); - - _elements = ParseSplitStringIntoElements (split.Where (s => s.Length > 0).ToArray ()); - } - } - - private NPath (string[] elements, bool isRelative, string? driveLetter) - { - _elements = elements; - _isRelative = isRelative; - _driveLetter = driveLetter; - } - - private string[] ParseSplitStringIntoElements (IEnumerable inputs) - { - var stack = new List (); - - foreach (var input in inputs.Where (input => input.Length != 0)) { - if (input == ".") { - if ((stack.Count > 0) && (stack.Last () != ".")) - continue; - } else if (input == "..") { - if (HasNonDotDotLastElement (stack)) { - stack.RemoveAt (stack.Count - 1); - continue; - } - if (!_isRelative) - throw new ArgumentException ("You cannot create a path that tries to .. past the root"); - } - stack.Add (input); - } - return stack.ToArray (); - } - - private static bool HasNonDotDotLastElement (List stack) - { - return stack.Count > 0 && stack[stack.Count - 1] != ".."; - } - - private string ParseDriveLetter (string path, out string? driveLetter) - { - if (path.Length >= 2 && path[1] == ':') { - driveLetter = path[0].ToString (); - return path.Substring (2); - } - - driveLetter = null; - return path; - } - - private static bool IsRelativeFromSplitString (string[] split) - { - if (split.Length < 2) - return true; - - return split[0].Length != 0 || !split.Any (s => s.Length > 0); - } - - public NPath Combine (params string[] append) - { - return Combine (append.Select (a => new NPath (a)).ToArray ()); - } - - public NPath Combine (params NPath[] append) - { - if (!append.All (p => p.IsRelative)) - throw new ArgumentException ("You cannot .Combine a non-relative path"); - - return new NPath (ParseSplitStringIntoElements (_elements.Concat (append.SelectMany (p => p._elements))), _isRelative, _driveLetter); - } - - public NPath Parent { - get { - if (_elements.Length == 0) - throw new InvalidOperationException ("Parent is called on an empty path"); - - var newElements = _elements.Take (_elements.Length - 1).ToArray (); - - return new NPath (newElements, _isRelative, _driveLetter); - } - } - - public NPath RelativeTo (NPath path) - { - if (!IsChildOf (path)) { - if (!IsRelative && !path.IsRelative && _driveLetter != path._driveLetter) - throw new ArgumentException ("Path.RelativeTo() was invoked with two paths that are on different volumes. invoked on: " + ToString () + " asked to be made relative to: " + path); - - NPath? commonParent = null; - foreach (var parent in RecursiveParents) { - commonParent = path.RecursiveParents.FirstOrDefault (otherParent => otherParent == parent); - - if (commonParent != null) - break; - } - - if (commonParent == null) - throw new ArgumentException ("Path.RelativeTo() was unable to find a common parent between " + ToString () + " and " + path); - - if (IsRelative && path.IsRelative && commonParent.IsEmpty ()) - throw new ArgumentException ("Path.RelativeTo() was invoked with two relative paths that do not share a common parent. Invoked on: " + ToString () + " asked to be made relative to: " + path); - - var depthDiff = path.Depth - commonParent.Depth; - return new NPath (Enumerable.Repeat ("..", depthDiff).Concat (_elements.Skip (commonParent.Depth)).ToArray (), true, null); - } - - return new NPath (_elements.Skip (path._elements.Length).ToArray (), true, null); - } - - public NPath ChangeExtension (string extension) - { - ThrowIfRoot (); - - var newElements = (string[]) _elements.Clone (); - newElements[newElements.Length - 1] = Path.ChangeExtension (_elements[_elements.Length - 1], WithDot (extension)); - if (extension == string.Empty) - newElements[newElements.Length - 1] = newElements[newElements.Length - 1].TrimEnd ('.'); - return new NPath (newElements, _isRelative, _driveLetter); - } - #endregion construction - - #region inspection - - public bool IsRelative { - get { return _isRelative; } - } - - public string FileName { - get { - ThrowIfRoot (); - - return _elements.Last (); - } - } - - public string FileNameWithoutExtension { - get { return Path.GetFileNameWithoutExtension (FileName); } - } - - public IEnumerable Elements { - get { return _elements; } - } - - public int Depth { - get { return _elements.Length; } - } - - public bool Exists (string append = "") - { - return Exists (new NPath (append)); - } - - public bool Exists (NPath append) - { - return FileExists (append) || DirectoryExists (append); - } - - public bool DirectoryExists (string append = "") - { - return DirectoryExists (new NPath (append)); - } - - public bool DirectoryExists (NPath append) - { - return Directory.Exists (Combine (append).ToString ()); - } - - public bool FileExists (string append = "") - { - return FileExists (new NPath (append)); - } - - public bool FileExists (NPath append) - { - return File.Exists (Combine (append).ToString ()); - } - - public string ExtensionWithDot { - get { - if (IsRoot) - throw new ArgumentException ("A root directory does not have an extension"); - - var last = _elements.Last (); - var index = last.LastIndexOf ("."); - if (index < 0) return String.Empty; - return last.Substring (index); - } - } - - public string InQuotes () - { - return "\"" + ToString () + "\""; - } - - public string InQuotes (SlashMode slashMode) - { - return "\"" + ToString (slashMode) + "\""; - } - - public override string ToString () - { - return ToString (SlashMode.Native); - } - - public string ToString (SlashMode slashMode) - { - // Check if it's linux root / - if (IsRoot && string.IsNullOrEmpty (_driveLetter)) - return Slash (slashMode).ToString (); - - if (_isRelative && _elements.Length == 0) - return "."; - - var sb = new StringBuilder (); - if (_driveLetter != null) { - sb.Append (_driveLetter); - sb.Append (":"); - } - if (!_isRelative) - sb.Append (Slash (slashMode)); - var first = true; - foreach (var element in _elements) { - if (!first) - sb.Append (Slash (slashMode)); - - sb.Append (element); - first = false; - } - return sb.ToString (); - } - - public static implicit operator string (NPath path) - { - return path.ToString (); - } - - static char Slash (SlashMode slashMode) - { - return slashMode switch { - SlashMode.Backward => '\\', - SlashMode.Forward => '/', - _ => Path.DirectorySeparatorChar, - }; - } - - public override bool Equals (Object? obj) - { - if (obj == null) - return false; - - // If parameter cannot be cast to Point return false. - if (!(obj is NPath p)) - return false; - - return Equals (p); - } - - public bool Equals (NPath? p) - { - if (p == null) - return false; - - if (p._isRelative != _isRelative) - return false; - - if (!string.Equals (p._driveLetter, _driveLetter, PathStringComparison)) - return false; - - if (p._elements.Length != _elements.Length) - return false; - - for (var i = 0; i != _elements.Length; i++) - if (!string.Equals (p._elements[i], _elements[i], PathStringComparison)) - return false; - - return true; - } - - public static bool operator == (NPath? a, NPath? b) - { - // If both are null, or both are same instance, return true. - if (ReferenceEquals (a, b)) - return true; - - // If one is null, but not both, return false. - if ((a is null) || (b is null)) - return false; - - // Return true if the fields match: - return a.Equals (b); - } - - public override int GetHashCode () - { - unchecked { - int hash = 17; - // Suitable nullity checks etc, of course :) - hash = hash * 23 + _isRelative.GetHashCode (); - foreach (var element in _elements) - hash = hash * 23 + element.GetHashCode (); - if (_driveLetter != null) - hash = hash * 23 + _driveLetter.GetHashCode (); - return hash; - } - } - - public int CompareTo (object? obj) - { - if (obj == null) - return -1; - - return this.ToString ().CompareTo (((NPath) obj).ToString ()); - } - - public static bool operator != (NPath? a, NPath? b) - { - return !(a == b); - } - - public bool HasExtension (params string[] extensions) - { - var extensionWithDotLower = ExtensionWithDot.ToLower (); - return extensions.Any (e => WithDot (e).ToLower () == extensionWithDotLower); - } - - private static string WithDot (string extension) - { - return extension.StartsWith (".") ? extension : "." + extension; - } - - private bool IsEmpty () - { - return _elements.Length == 0; - } - - public bool IsRoot { - get { return _elements.Length == 0 && !_isRelative; } - } - - #endregion inspection - - #region directory enumeration - - public IEnumerable Files (string filter, bool recurse = false) - { - return Directory.GetFiles (ToString (), filter, recurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Select (s => new NPath (s)); - } - - public IEnumerable Files (bool recurse = false) - { - return Files ("*", recurse); - } - - public IEnumerable Contents (string filter, bool recurse = false) - { - return Files (filter, recurse).Concat (Directories (filter, recurse)); - } - - public IEnumerable Contents (bool recurse = false) - { - return Contents ("*", recurse); - } - - public IEnumerable Directories (string filter, bool recurse = false) - { - return Directory.GetDirectories (ToString (), filter, recurse ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly).Select (s => new NPath (s)); - } - - public IEnumerable Directories (bool recurse = false) - { - return Directories ("*", recurse); - } - - #endregion - - #region filesystem writing operations - public NPath CreateFile () - { - ThrowIfRelative (); - ThrowIfRoot (); - EnsureParentDirectoryExists (); - File.WriteAllBytes (ToString (), new byte[0]); - return this; - } - - public NPath CreateFile (string file) - { - return CreateFile (new NPath (file)); - } - - public NPath CreateFile (NPath file) - { - if (!file.IsRelative) - throw new ArgumentException ("You cannot call CreateFile() on an existing path with a non relative argument"); - return Combine (file).CreateFile (); - } - - public NPath CreateDirectory () - { - ThrowIfRelative (); - - if (IsRoot) - throw new NotSupportedException ("CreateDirectory is not supported on a root level directory because it would be dangerous:" + ToString ()); - - Directory.CreateDirectory (ToString ()); - return this; - } - - public NPath CreateDirectory (string directory) - { - return CreateDirectory (new NPath (directory)); - } - - public NPath CreateDirectory (NPath directory) - { - if (!directory.IsRelative) - throw new ArgumentException ("Cannot call CreateDirectory with an absolute argument"); - - return Combine (directory).CreateDirectory (); - } - - public NPath? Copy (string dest) - { - return Copy (new NPath (dest)); - } - - public NPath? Copy (string dest, Func fileFilter) - { - return Copy (new NPath (dest), fileFilter); - } - - public NPath? Copy (NPath dest) - { - return Copy (dest, p => true); - } - - public NPath? Copy (NPath dest, Func fileFilter) - { - ThrowIfRelative (); - if (dest.IsRelative) - dest = Parent.Combine (dest); - - if (dest.DirectoryExists ()) - return CopyWithDeterminedDestination (dest.Combine (FileName), fileFilter); - - return CopyWithDeterminedDestination (dest, fileFilter); - } - - public NPath MakeAbsolute () - { - if (!IsRelative) - return this; - - return NPath.CurrentDirectory.Combine (this); - } - - NPath? CopyWithDeterminedDestination (NPath absoluteDestination, Func fileFilter) - { - if (absoluteDestination.IsRelative) - throw new ArgumentException ("absoluteDestination must be absolute"); - - if (FileExists ()) { - if (!fileFilter (absoluteDestination)) - return null; - - absoluteDestination.EnsureParentDirectoryExists (); - - File.Copy (ToString (), absoluteDestination.ToString (), true); - return absoluteDestination; - } - - if (DirectoryExists ()) { - absoluteDestination.EnsureDirectoryExists (); - foreach (var thing in Contents ()) - thing.CopyWithDeterminedDestination (absoluteDestination.Combine (thing.RelativeTo (this)), fileFilter); - return absoluteDestination; - } - - throw new ArgumentException ("Copy() called on path that doesnt exist: " + ToString ()); - } - - public void Delete (DeleteMode deleteMode = DeleteMode.Normal) - { - ThrowIfRelative (); - - if (IsRoot) - throw new NotSupportedException ("Delete is not supported on a root level directory because it would be dangerous:" + ToString ()); - - if (FileExists ()) - File.Delete (ToString ()); - else if (DirectoryExists ()) - try { - Directory.Delete (ToString (), true); - } catch (IOException) { - if (deleteMode == DeleteMode.Normal) - throw; - } - else - throw new InvalidOperationException ("Trying to delete a path that does not exist: " + ToString ()); - } - - public void DeleteIfExists (DeleteMode deleteMode = DeleteMode.Normal) - { - ThrowIfRelative (); - - if (FileExists () || DirectoryExists ()) - Delete (deleteMode); - } - - public NPath DeleteContents () - { - ThrowIfRelative (); - - if (IsRoot) - throw new NotSupportedException ("DeleteContents is not supported on a root level directory because it would be dangerous:" + ToString ()); - - if (FileExists ()) - throw new InvalidOperationException ("It is not valid to perform this operation on a file"); - - if (DirectoryExists ()) { - try { - Files ().Delete (); - Directories ().Delete (); - } catch (IOException) { - if (Files (true).Any ()) - throw; - } - - return this; - } - - return EnsureDirectoryExists (); - } - - public static NPath CreateTempDirectory (string myprefix) - { - var random = new Random (); - while (true) { - var candidate = new NPath (Path.GetTempPath () + "/" + myprefix + "_" + random.Next ()); - if (!candidate.Exists ()) - return candidate.CreateDirectory (); - } - } - - public NPath Move (string dest) - { - return Move (new NPath (dest)); - } - - public NPath Move (NPath dest) - { - ThrowIfRelative (); - - if (IsRoot) - throw new NotSupportedException ("Move is not supported on a root level directory because it would be dangerous:" + ToString ()); - - if (dest.IsRelative) - return Move (Parent.Combine (dest)); - - if (dest.DirectoryExists ()) - return Move (dest.Combine (FileName)); - - if (FileExists ()) { - dest.EnsureParentDirectoryExists (); - File.Move (ToString (), dest.ToString ()); - return dest; - } - - if (DirectoryExists ()) { - Directory.Move (ToString (), dest.ToString ()); - return dest; - } - - throw new ArgumentException ("Move() called on a path that doesn't exist: " + ToString ()); - } - - #endregion - - #region special paths - - public static NPath CurrentDirectory { - get { - return new NPath (Directory.GetCurrentDirectory ()); - } - } - - public static NPath HomeDirectory { - get { - if (Path.DirectorySeparatorChar == '\\') - return new NPath (Environment.GetEnvironmentVariable ("USERPROFILE")!); - return new NPath (Environment.GetEnvironmentVariable ("HOME")!); - } - } - - public static NPath SystemTemp { - get { - return new NPath (Path.GetTempPath ()); - } - } - - #endregion - - private void ThrowIfRelative () - { - if (_isRelative) - throw new ArgumentException ("You are attempting an operation on a Path that requires an absolute path, but the path is relative"); - } - - private void ThrowIfRoot () - { - if (IsRoot) - throw new ArgumentException ("You are attempting an operation that is not valid on a root level directory"); - } - - public NPath EnsureDirectoryExists (string append = "") - { - return EnsureDirectoryExists (new NPath (append)); - } - - public NPath EnsureDirectoryExists (NPath append) - { - var combined = Combine (append); - if (combined.DirectoryExists ()) - return combined; - combined.EnsureParentDirectoryExists (); - combined.CreateDirectory (); - return combined; - } - - public NPath EnsureParentDirectoryExists () - { - var parent = Parent; - parent.EnsureDirectoryExists (); - return parent; - } - - public NPath FileMustExist () - { - if (!FileExists ()) - throw new FileNotFoundException ("File was expected to exist : " + ToString ()); - - return this; - } - - public NPath DirectoryMustExist () - { - if (!DirectoryExists ()) - throw new DirectoryNotFoundException ("Expected directory to exist : " + ToString ()); - - return this; - } - - public bool IsChildOf (string potentialBasePath) - { - return IsChildOf (new NPath (potentialBasePath)); - } - - public bool IsChildOf (NPath potentialBasePath) - { - if ((IsRelative && !potentialBasePath.IsRelative) || !IsRelative && potentialBasePath.IsRelative) - throw new ArgumentException ("You can only call IsChildOf with two relative paths, or with two absolute paths"); - - // If the other path is the root directory, then anything is a child of it as long as it's not a Windows path - if (potentialBasePath.IsRoot) { - if (_driveLetter != potentialBasePath._driveLetter) - return false; - return true; - } - - if (IsEmpty ()) - return false; - - if (Equals (potentialBasePath)) - return true; - - return Parent.IsChildOf (potentialBasePath); - } - - public IEnumerable RecursiveParents { - get { - var candidate = this; - while (true) { - if (candidate.IsEmpty ()) - yield break; - - candidate = candidate.Parent; - yield return candidate; - } - } - } - - public NPath WriteAllText (string contents) - { - ThrowIfRelative (); - EnsureParentDirectoryExists (); - File.WriteAllText (ToString (), contents); - return this; - } - - public string ReadAllText () - { - ThrowIfRelative (); - return File.ReadAllText (ToString ()); - } - - public NPath WriteAllLines (string[] contents) - { - ThrowIfRelative (); - EnsureParentDirectoryExists (); - File.WriteAllLines (ToString (), contents); - return this; - } - - public string[] ReadAllLines () - { - ThrowIfRelative (); - return File.ReadAllLines (ToString ()); - } - - public IEnumerable CopyFiles (NPath destination, bool recurse, Func? fileFilter = null) - { - destination.EnsureDirectoryExists (); - return Files (recurse).Where (fileFilter ?? AlwaysTrue).Select (file => file.Copy (destination.Combine (file.RelativeTo (this)))).ToArray (); - } - - public IEnumerable MoveFiles (NPath destination, bool recurse, Func? fileFilter = null) - { - if (IsRoot) - throw new NotSupportedException ("MoveFiles is not supported on this directory because it would be dangerous:" + ToString ()); - - destination.EnsureDirectoryExists (); - return Files (recurse).Where (fileFilter ?? AlwaysTrue).Select (file => file.Move (destination.Combine (file.RelativeTo (this)))).ToArray (); - } - - static bool AlwaysTrue (NPath p) - { - return true; - } - - private static bool IsLinux () - { - return Directory.Exists ("/proc"); - } - } - - public static class Extensions - { - public static IEnumerable Copy (this IEnumerable self, string dest) - { - return Copy (self, new NPath (dest)); - } - - public static IEnumerable Copy (this IEnumerable self, NPath dest) - { - if (dest.IsRelative) - throw new ArgumentException ("When copying multiple files, the destination cannot be a relative path"); - dest.EnsureDirectoryExists (); - return self.Select (p => p.Copy (dest.Combine (p.FileName))).ToArray (); - } - - public static IEnumerable Move (this IEnumerable self, string dest) - { - return Move (self, new NPath (dest)); - } - - public static IEnumerable Move (this IEnumerable self, NPath dest) - { - if (dest.IsRelative) - throw new ArgumentException ("When moving multiple files, the destination cannot be a relative path"); - dest.EnsureDirectoryExists (); - return self.Select (p => p.Move (dest.Combine (p.FileName))).ToArray (); - } - - public static IEnumerable Delete (this IEnumerable self) - { - foreach (var p in self) - p.Delete (); - return self; - } - - public static IEnumerable InQuotes (this IEnumerable self, SlashMode forward = SlashMode.Native) - { - return self.Select (p => p.InQuotes (forward)); - } - - public static NPath ToNPath (this string path) - { - return new NPath (path); - } - } - - public enum SlashMode - { - Native, - Forward, - Backward - } - - public enum DeleteMode - { - Normal, - Soft - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/Mono.Linker.Tests.csproj b/src/coreclr/tools/aot/Mono.Linker.Tests/Mono.Linker.Tests.csproj deleted file mode 100644 index 479c971ed03fd..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/Mono.Linker.Tests.csproj +++ /dev/null @@ -1,51 +0,0 @@ - - - - $(NetCoreAppToolCurrent) - enable - - false - true - x64;x86 - AnyCPU - - linux-x64;win-x64;osx-x64 - Debug;Release;Checked - - - - - - - - - - - - - - - - $(RuntimeBinDir) - - - $(MicrosoftNetCoreAppRuntimePackRidLibTfmDir) - - - $(Configuration) - - - $(ArtifactsDir) - - - $(ArtifactsBinDir) - - - $(_DirectoryBuildPropsBasePath) - - - $(TargetArchitecture) - - - - diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestCase.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestCase.cs deleted file mode 100644 index a9c383d52c2d3..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestCase.cs +++ /dev/null @@ -1,59 +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.Linq; -using Mono.Linker.Tests.Extensions; - -namespace Mono.Linker.Tests.TestCases -{ - public class TestCase - { - public TestCase (NPath sourceFile, NPath rootCasesDirectory, NPath originalTestCaseAssemblyPath) - { - SourceFile = sourceFile; - RootCasesDirectory = rootCasesDirectory; - OriginalTestCaseAssemblyPath = originalTestCaseAssemblyPath; - Name = sourceFile.FileNameWithoutExtension; - var fullyRelative = sourceFile.RelativeTo (rootCasesDirectory); - var displayNameRelative = fullyRelative.RelativeTo (new NPath (fullyRelative.Elements.First ())); - string displayNameBase = displayNameRelative.Depth == 1 ? "" : displayNameRelative.Parent.ToString (SlashMode.Forward).Replace ('/', '.') + "."; - DisplayName = $"{displayNameBase}{sourceFile.FileNameWithoutExtension}"; - - // A little hacky, but good enough for name. No reason why namespace & type names - // should not follow the directory structure - //ReconstructedFullTypeName = $"{sourceFile.Parent.RelativeTo (rootCasesDirectory.Parent).ToString (SlashMode.Forward).Replace ('/', '.')}.{sourceFile.FileNameWithoutExtension}"; - ReconstructedFullTypeName = $"Mono.Linker.Tests.Cases.{fullyRelative.Parent.ToString (SlashMode.Forward).Replace ('/', '.')}.{sourceFile.FileNameWithoutExtension}"; - - var firstParentRelativeToRoot = SourceFile.RelativeTo (rootCasesDirectory).Elements.First (); - TestSuiteDirectory = rootCasesDirectory.Combine (firstParentRelativeToRoot); - } - - public NPath RootCasesDirectory { get; } - - public string Name { get; } - - public string DisplayName { get; } - - public NPath SourceFile { get; } - - public NPath OriginalTestCaseAssemblyPath { get; } - - public string ReconstructedFullTypeName { get; } - - public bool HasLinkXmlFile { - get { return SourceFile.ChangeExtension ("xml").FileExists (); } - } - - public NPath LinkXmlFile { - get { - if (!HasLinkXmlFile) - throw new InvalidOperationException ("This test case does not have a link xml file"); - - return SourceFile.ChangeExtension ("xml"); - } - } - - public NPath TestSuiteDirectory { get; } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs deleted file mode 100644 index 71c527c459d77..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestDatabase.cs +++ /dev/null @@ -1,76 +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.Collections.Generic; -using System.IO; -using System.Linq; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCasesRunner; - -namespace Mono.Linker.Tests.TestCases -{ - public static class TestDatabase - { - private static TestCase[]? _cachedAllCases; - - public static IEnumerable DataFlow () - { - return TestNamesBySuiteName ("DataFlow"); - } - - public static IEnumerable Repro () - { - return TestNamesBySuiteName ("Repro"); - } - - public static IEnumerable RequiresCapability () - { - return TestNamesBySuiteName ("RequiresCapability"); - } - - public static TestCaseCollector CreateCollector () - { - GetDirectoryPaths (out string rootSourceDirectory, out string testCaseAssemblyPath); - return new TestCaseCollector (rootSourceDirectory, testCaseAssemblyPath); - } - - public static NPath TestCasesRootDirectory { - get { - GetDirectoryPaths (out string rootSourceDirectory, out string _); - return rootSourceDirectory.ToNPath (); - } - } - - static IEnumerable AllCases () - { - if (_cachedAllCases == null) - _cachedAllCases = CreateCollector () - .Collect () - .Where (c => c != null) - .OrderBy (c => c.DisplayName) - .ToArray (); - - return _cachedAllCases; - } - - public static TestCase? GetTestCaseFromName (string name) - { - return AllCases ().FirstOrDefault (c => c.Name == name); - } - - static IEnumerable TestNamesBySuiteName (string suiteName) - { - return AllCases () - .Where (c => c.TestSuiteDirectory.FileName == suiteName) - .Select (c => c.DisplayName) - .OrderBy (c => c) - .Select (c => new object[] { c }); - } - - static void GetDirectoryPaths (out string rootSourceDirectory, out string testCaseAssemblyPath) - { - rootSourceDirectory = Path.GetFullPath (Path.Combine (PathUtilities.GetTestsSourceRootDirectory (), "Mono.Linker.Tests.Cases")); - testCaseAssemblyPath = PathUtilities.GetTestAssemblyPath ("Mono.Linker.Tests.Cases"); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestSuites.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestSuites.cs deleted file mode 100644 index 00cbb1437c10c..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCases/TestSuites.cs +++ /dev/null @@ -1,45 +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 Mono.Linker.Tests.TestCasesRunner; -using Xunit; - -namespace Mono.Linker.Tests.TestCases -{ - public class All - { - - [Theory] - [MemberData(nameof(TestDatabase.DataFlow), MemberType = typeof(TestDatabase))] - public void DataFlow(string t) - { - Run(t); - } - - [Theory] - [MemberData (nameof (TestDatabase.Repro), MemberType = typeof (TestDatabase))] - public void Repro (string t) - { - Run (t); - } - - [Theory] - [MemberData(nameof(TestDatabase.RequiresCapability), MemberType = typeof(TestDatabase))] - public void RequiresCapability(string t) - { - Run(t); - } - - protected virtual void Run(string testName) - { - TestCase testCase = TestDatabase.GetTestCaseFromName(testName) ?? throw new InvalidOperationException($"Unknown test {testName}"); - var runner = new TestRunner(new ObjectFactory()); - var linkedResult = runner.Run(testCase); - if (linkedResult != null) - { - new ResultChecker().Check(linkedResult); - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs deleted file mode 100644 index cac049b732ebb..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs +++ /dev/null @@ -1,960 +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.Linq; -using System.Text; -using FluentAssertions; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Extensions; -using Xunit; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class AssemblyChecker - { - readonly AssemblyDefinition originalAssembly, linkedAssembly; - - HashSet linkedMembers; - readonly HashSet verifiedGeneratedFields = new HashSet (); - readonly HashSet verifiedEventMethods = new HashSet (); - readonly HashSet verifiedGeneratedTypes = new HashSet (); - bool checkNames; - - public AssemblyChecker (AssemblyDefinition original, AssemblyDefinition linked) - { - this.originalAssembly = original; - this.linkedAssembly = linked; - this.linkedMembers = new (StringComparer.Ordinal); - - checkNames = original.MainModule.GetTypeReferences ().Any (attr => - attr.Name == nameof (RemovedNameValueAttribute)); - } - - public void Verify () - { - VerifyExportedTypes (originalAssembly, linkedAssembly); - - VerifyCustomAttributes (originalAssembly, linkedAssembly); - VerifySecurityAttributes (originalAssembly, linkedAssembly); - - foreach (var originalModule in originalAssembly.Modules) - VerifyModule (originalModule, linkedAssembly.Modules.FirstOrDefault (m => m.Name == originalModule.Name)); - - VerifyResources (originalAssembly, linkedAssembly); - VerifyReferences (originalAssembly, linkedAssembly); - - foreach (var s in linkedAssembly.MainModule.AllMembers ().Select (s => s.FullName)) { - this.linkedMembers.Add (s); - } - - var membersToAssert = originalAssembly.MainModule.Types; - foreach (var originalMember in membersToAssert) { - if (originalMember is TypeDefinition td) { - if (td.Name == "") { - linkedMembers.Remove (td.Name); - continue; - } - - TypeDefinition linkedType = linkedAssembly.MainModule.GetType (originalMember.FullName); - VerifyTypeDefinition (td, linkedType); - linkedMembers.Remove (td.FullName); - - continue; - } - - throw new NotImplementedException ($"Don't know how to check member of type {originalMember.GetType ()}"); - } - - Assert.Empty (linkedMembers); - } - - protected virtual void VerifyModule (ModuleDefinition original, ModuleDefinition? linked) - { - // We never link away a module today so let's make sure the linked one isn't null - if (linked == null) { - Assert.True (false, $"Linked assembly `{original.Assembly.Name.Name}` is missing module `{original.Name}`"); - return; - } - - var expected = original.Assembly.MainModule.AllDefinedTypes () - .SelectMany (t => GetCustomAttributeCtorValues (t, nameof (KeptModuleReferenceAttribute))) - .ToArray (); - - var actual = linked.ModuleReferences - .Select (name => name.Name) - .ToArray (); - - Assert.Equal (expected, actual); - - VerifyCustomAttributes (original, linked); - } - - protected virtual void VerifyTypeDefinition (TypeDefinition original, TypeDefinition? linked) - { - if (linked != null && verifiedGeneratedTypes.Contains (linked.FullName)) - return; - - ModuleDefinition? linkedModule = linked?.Module; - - // - // Little bit complex check to allow easier test writing to match - // - It has [Kept] attribute or any variation of it - // - It contains Main method - // - It contains at least one member which has [Kept] attribute (not recursive) - // - bool expectedKept = - original.HasAttributeDerivedFrom (nameof (KeptAttribute)) || - (linked != null && linkedModule!.Assembly.EntryPoint?.DeclaringType == linked) || - original.AllMembers ().Any (l => l.HasAttribute (nameof (KeptAttribute))); - - if (!expectedKept) { - if (linked != null) - Assert.True (false, $"Type `{original}' should have been removed"); - - return; - } - - bool prev = checkNames; - checkNames |= original.HasAttribute (nameof (VerifyMetadataNamesAttribute)); - - VerifyTypeDefinitionKept (original, linked); - - checkNames = prev; - - if (original.HasAttribute (nameof (CreatedMemberAttribute))) { - foreach (var attr in original.CustomAttributes.Where (l => l.AttributeType.Name == nameof (CreatedMemberAttribute))) { - var newName = original.FullName + "::" + attr.ConstructorArguments[0].Value.ToString (); - - if (linkedMembers!.RemoveWhere (l => l.Contains (newName)) != 1) - Assert.True (false, $"Newly created member '{newName}' was not found"); - } - } - } - - protected virtual void VerifyTypeDefinitionKept (TypeDefinition original, TypeDefinition? linked) - { - if (linked == null) { - Assert.True (false, $"Type `{original}' should have been kept"); - return; - } - - if (!original.IsInterface) - VerifyBaseType (original, linked); - - VerifyInterfaces (original, linked); - VerifyPseudoAttributes (original, linked); - VerifyGenericParameters (original, linked); - VerifyCustomAttributes (original, linked); - VerifySecurityAttributes (original, linked); - - VerifyFixedBufferFields (original, linked); - - foreach (var td in original.NestedTypes) { - VerifyTypeDefinition (td, linked?.NestedTypes.FirstOrDefault (l => td.FullName == l.FullName)); - linkedMembers.Remove (td.FullName); - } - - // Need to check properties before fields so that the KeptBackingFieldAttribute is handled correctly - foreach (var p in original.Properties) { - VerifyProperty (p, linked.Properties.FirstOrDefault (l => p.Name == l.Name), linked); - linkedMembers.Remove (p.FullName); - } - // Need to check events before fields so that the KeptBackingFieldAttribute is handled correctly - foreach (var e in original.Events) { - VerifyEvent (e, linked.Events.FirstOrDefault (l => e.Name == l.Name), linked); - linkedMembers.Remove (e.FullName); - } - - // Need to check delegate cache fields before the normal field check - VerifyDelegateBackingFields (original, linked); - - foreach (var f in original.Fields) { - if (verifiedGeneratedFields.Contains (f.FullName)) - continue; - VerifyField (f, linked.Fields.FirstOrDefault (l => f.Name == l.Name)); - linkedMembers.Remove (f.FullName); - } - - foreach (var m in original.Methods) { - if (verifiedEventMethods.Contains (m.FullName)) - continue; - var msign = m.GetSignature (); - VerifyMethod (m, linked.Methods.FirstOrDefault (l => msign == l.GetSignature ())); - linkedMembers.Remove (m.FullName); - } - } - - void VerifyBaseType (TypeDefinition src, TypeDefinition linked) - { - string expectedBaseName; - var expectedBaseGenericAttr = src.CustomAttributes.FirstOrDefault (w => w.AttributeType.Name == nameof (KeptBaseTypeAttribute) && w.ConstructorArguments.Count > 1); - if (expectedBaseGenericAttr != null) { - expectedBaseName = FormatBaseOrInterfaceAttributeValue (expectedBaseGenericAttr); - } else { - var defaultBaseType = src.IsEnum ? "System.Enum" : src.IsValueType ? "System.ValueType" : "System.Object"; - expectedBaseName = GetCustomAttributeCtorValues (src, nameof (KeptBaseTypeAttribute)).FirstOrDefault ()?.ToString () ?? defaultBaseType; - } - - if (expectedBaseName != linked.BaseType?.FullName) { - Assert.True (false, $"Incorrect base type on : {linked.Name}. Expected {expectedBaseName}, actual {linked.BaseType?.FullName}"); - } - } - - void VerifyInterfaces (TypeDefinition src, TypeDefinition linked) - { - var expectedInterfaces = new HashSet (src.CustomAttributes - .Where (w => w.AttributeType.Name == nameof (KeptInterfaceAttribute)) - .Select (FormatBaseOrInterfaceAttributeValue)); - if (expectedInterfaces.Count == 0) { - Assert.False (linked.HasInterfaces, $"Type `{src}' has unexpected interfaces"); - } else { - foreach (var iface in linked.Interfaces) { - if (!expectedInterfaces.Remove (iface.InterfaceType.FullName)) { - Assert.True (expectedInterfaces.Remove (iface.InterfaceType.Resolve ().FullName), $"Type `{src}' interface `{iface.InterfaceType.Resolve ().FullName}' should have been removed"); - } - } - - if (expectedInterfaces.Count != 0) - Assert.True (false, $"Expected interfaces were not found on {src}"); - } - } - - static string FormatBaseOrInterfaceAttributeValue (CustomAttribute attr) - { - if (attr.ConstructorArguments.Count == 1) - return attr.ConstructorArguments[0].Value.ToString ()!; - - StringBuilder builder = new StringBuilder (); - builder.Append (attr.ConstructorArguments[0].Value); - builder.Append ("<"); - bool separator = false; - foreach (var caa in (CustomAttributeArgument[]) attr.ConstructorArguments[1].Value) { - if (separator) - builder.Append (","); - else - separator = true; - - var arg = (CustomAttributeArgument) caa.Value; - builder.Append (arg.Value); - } - - builder.Append (">"); - return builder.ToString (); - } - - void VerifyField (FieldDefinition src, FieldDefinition? linked) - { - bool expectedKept = ShouldBeKept (src); - - if (!expectedKept) { - if (linked != null) - Assert.True (false, $"Field `{src}' should have been removed"); - - return; - } - - VerifyFieldKept (src, linked); - } - - void VerifyFieldKept (FieldDefinition src, FieldDefinition? linked) - { - if (linked == null) { - Assert.True (false, $"Field `{src}' should have been kept"); - return; - } - - if (!object.Equals (src.Constant, linked.Constant)) { - Assert.True (false, $"Field '{src}' value doesn's match. Expected {src.Constant}, actual {linked.Constant}"); - } - - VerifyPseudoAttributes (src, linked); - VerifyCustomAttributes (src, linked); - } - - void VerifyProperty (PropertyDefinition src, PropertyDefinition? linked, TypeDefinition linkedType) - { - VerifyMemberBackingField (src, linkedType); - - bool expectedKept = ShouldBeKept (src); - - if (!expectedKept) { - if (linked != null) - Assert.True (false, $"Property `{src}' should have been removed"); - - return; - } - - if (linked == null) { - Assert.True (false, $"Property `{src}' should have been kept"); - return; - } - - if (src.Constant != linked.Constant) { - Assert.True (false, $"Property '{src}' value doesn's match. Expected {src.Constant}, actual {linked.Constant}"); - } - - VerifyPseudoAttributes (src, linked); - VerifyCustomAttributes (src, linked); - } - - void VerifyEvent (EventDefinition src, EventDefinition? linked, TypeDefinition linkedType) - { - VerifyMemberBackingField (src, linkedType); - - bool expectedKept = ShouldBeKept (src); - - if (!expectedKept) { - if (linked != null) - Assert.True (false, $"Event `{src}' should have been removed"); - - return; - } - - if (linked == null) { - Assert.True (false, $"Event `{src}' should have been kept"); - return; - } - - if (src.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptEventAddMethodAttribute))) { - VerifyMethodInternal (src.AddMethod, linked.AddMethod, true); - verifiedEventMethods.Add (src.AddMethod.FullName); - linkedMembers.Remove (src.AddMethod.FullName); - } - - if (src.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptEventRemoveMethodAttribute))) { - VerifyMethodInternal (src.RemoveMethod, linked.RemoveMethod, true); - verifiedEventMethods.Add (src.RemoveMethod.FullName); - linkedMembers.Remove (src.RemoveMethod.FullName); - } - - VerifyPseudoAttributes (src, linked); - VerifyCustomAttributes (src, linked); - } - - void VerifyMethod (MethodDefinition src, MethodDefinition? linked) - { - bool expectedKept = ShouldMethodBeKept (src); - VerifyMethodInternal (src, linked, expectedKept); - } - - - void VerifyMethodInternal (MethodDefinition src, MethodDefinition? linked, bool expectedKept) - { - if (!expectedKept) { - if (linked != null) - Assert.True (false, $"Method `{src.FullName}' should have been removed"); - - return; - } - - VerifyMethodKept (src, linked); - } - - void VerifyMemberBackingField (IMemberDefinition src, TypeDefinition linkedType) - { - var keptBackingFieldAttribute = src.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == nameof (KeptBackingFieldAttribute)); - if (keptBackingFieldAttribute == null) - return; - - var backingFieldName = src.MetadataToken.TokenType == TokenType.Property - ? $"<{src.Name}>k__BackingField" : src.Name; - var srcField = src.DeclaringType.Fields.FirstOrDefault (f => f.Name == backingFieldName); - - if (srcField == null) { - // Can add more here if necessary - backingFieldName = backingFieldName.Replace ("System.Int32", "int"); - backingFieldName = backingFieldName.Replace ("System.String", "string"); - backingFieldName = backingFieldName.Replace ("System.Char", "char"); - - srcField = src.DeclaringType.Fields.FirstOrDefault (f => f.Name == backingFieldName); - } - - if (srcField == null) { - Assert.True (false, $"{src.MetadataToken.TokenType} `{src}', could not locate the expected backing field {backingFieldName}"); - return; - } - - VerifyFieldKept (srcField, linkedType?.Fields.FirstOrDefault (l => srcField.Name == l.Name)); - verifiedGeneratedFields.Add (srcField.FullName); - linkedMembers.Remove (srcField.FullName); - } - - protected virtual void VerifyMethodKept (MethodDefinition src, MethodDefinition? linked) - { - if (linked == null) { - Assert.True (false, $"Method `{src.FullName}' should have been kept"); - return; - } - - VerifyPseudoAttributes (src, linked); - VerifyGenericParameters (src, linked); - VerifyCustomAttributes (src, linked); - VerifyCustomAttributes (src.MethodReturnType, linked.MethodReturnType); - VerifyParameters (src, linked); - VerifySecurityAttributes (src, linked); - VerifyArrayInitializers (src, linked); - VerifyMethodBody (src, linked); - } - - protected virtual void VerifyMethodBody (MethodDefinition src, MethodDefinition linked) - { - if (!src.HasBody) - return; - - VerifyInstructions (src, linked); - VerifyLocals (src, linked); - } - - protected static void VerifyInstructions (MethodDefinition src, MethodDefinition linked) - { - VerifyBodyProperties ( - src, - linked, - nameof (ExpectedInstructionSequenceAttribute), - nameof (ExpectBodyModifiedAttribute), - "instructions", - m => FormatMethodBody (m.Body), - attr => GetStringArrayAttributeValue (attr)!.ToArray ()); - } - - public static string[] FormatMethodBody (MethodBody body) - { - List<(Instruction?, string)> result = new List<(Instruction?, string)> (body.Instructions.Count); - for (int index = 0; index < body.Instructions.Count; index++) { - var instruction = body.Instructions[index]; - result.Add ((instruction, FormatInstruction (instruction))); - } - - HashSet<(Instruction, Instruction)> existingTryBlocks = new HashSet<(Instruction, Instruction)> (); - foreach (var exHandler in body.ExceptionHandlers) { - if (existingTryBlocks.Add ((exHandler.TryStart, exHandler.TryEnd!))) { - InsertBeforeInstruction (exHandler.TryStart, ".try"); - if (exHandler.TryEnd != null) - InsertBeforeInstruction (exHandler.TryEnd, ".endtry"); - else - Append (".endtry"); - } - - if (exHandler.HandlerStart != null) - InsertBeforeInstruction (exHandler.HandlerStart, ".catch"); - - if (exHandler.HandlerEnd != null) - InsertBeforeInstruction (exHandler.HandlerEnd, ".endcatch"); - else - Append (".endcatch"); - - if (exHandler.FilterStart != null) - InsertBeforeInstruction (exHandler.FilterStart, ".filter"); - } - - return result.Select (i => i.Item2).ToArray (); - - void InsertBeforeInstruction (Instruction instruction, string text) => - result.Insert (result.FindIndex (i => i.Item1 == instruction), (null, text)); - - void Append (string text) => - result.Add ((null, text)); - } - - static string FormatInstruction (Instruction instr) - { - switch (instr.OpCode.FlowControl) { - case FlowControl.Branch: - case FlowControl.Cond_Branch: - if (instr.Operand is Instruction target) - return $"{instr.OpCode.ToString ()} il_{target.Offset.ToString ("x")}"; - - break; - } - - switch (instr.OpCode.Code) { - case Code.Ldc_I4: - if (instr.Operand is int ivalue) - return $"{instr.OpCode.ToString ()} 0x{ivalue.ToString ("x")}"; - - throw new NotImplementedException (instr.Operand.GetType ().ToString ()); - case Code.Ldc_I4_S: - if (instr.Operand is sbyte bvalue) - return $"{instr.OpCode.ToString ()} 0x{bvalue.ToString ("x")}"; - - throw new NotImplementedException (instr.Operand.GetType ().ToString ()); - case Code.Ldc_I8: - if (instr.Operand is long lvalue) - return $"{instr.OpCode.ToString ()} 0x{lvalue.ToString ("x")}"; - - throw new NotImplementedException (instr.Operand.GetType ().ToString ()); - - case Code.Ldc_R4: - if (instr.Operand is float fvalue) - return $"{instr.OpCode.ToString ()} {fvalue.ToString ()}"; - - throw new NotImplementedException (instr.Operand.GetType ().ToString ()); - - case Code.Ldc_R8: - if (instr.Operand is double dvalue) - return $"{instr.OpCode.ToString ()} {dvalue.ToString ()}"; - - throw new NotImplementedException (instr.Operand.GetType ().ToString ()); - - case Code.Ldstr: - if (instr.Operand is string svalue) - return $"{instr.OpCode.ToString ()} '{svalue}'"; - - throw new NotImplementedException (instr.Operand.GetType ().ToString ()); - - default: { - string? operandString = null; - switch (instr.OpCode.OperandType) { - case OperandType.InlineField: - case OperandType.InlineMethod: - case OperandType.InlineType: - case OperandType.InlineTok: - operandString = instr.Operand switch { - FieldReference fieldRef => fieldRef.FullName, - MethodReference methodRef => methodRef.FullName, - TypeReference typeRef => typeRef.FullName, - _ => null - }; - break; - } - - if (operandString != null) - return $"{instr.OpCode.ToString ()} {operandString}"; - else - return instr.OpCode.ToString (); - } - } - } - static void VerifyLocals (MethodDefinition src, MethodDefinition linked) - { - VerifyBodyProperties ( - src, - linked, - nameof (ExpectedLocalsSequenceAttribute), - nameof (ExpectLocalsModifiedAttribute), - "locals", - m => m.Body.Variables.Select (v => v.VariableType.ToString ()).ToArray (), - attr => GetStringOrTypeArrayAttributeValue (attr).ToArray ()); - } - - public static void VerifyBodyProperties (MethodDefinition src, MethodDefinition linked, string sequenceAttributeName, string expectModifiedAttributeName, - string propertyDescription, - Func valueCollector, - Func getExpectFromSequenceAttribute) - { - var expectedSequenceAttribute = src.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == sequenceAttributeName); - var linkedValues = valueCollector (linked); - var srcValues = valueCollector (src); - - if (src.CustomAttributes.Any (attr => attr.AttributeType.Name == expectModifiedAttributeName)) { - linkedValues.Should ().BeEquivalentTo (srcValues, $"Expected method `{src} to have {propertyDescription} modified, however, the {propertyDescription} were the same as the original\n{FormattingUtils.FormatSequenceCompareFailureMessage (linkedValues, srcValues)}"); - } else if (expectedSequenceAttribute != null) { - var expected = getExpectFromSequenceAttribute (expectedSequenceAttribute).ToArray (); - linkedValues.Should ().BeEquivalentTo (expected, $"Expected method `{src} to have it's {propertyDescription} modified, however, the sequence of {propertyDescription} does not match the expected value\n{FormattingUtils.FormatSequenceCompareFailureMessage2 (linkedValues, expected, srcValues)}"); - } else { - linkedValues.Should ().BeEquivalentTo (srcValues, $"Expected method `{src} to have it's {propertyDescription} unchanged, however, the {propertyDescription} differ from the original\n{FormattingUtils.FormatSequenceCompareFailureMessage (linkedValues, srcValues)}"); - } - } - - void VerifyReferences (AssemblyDefinition original, AssemblyDefinition linked) - { - var expected = original.MainModule.AllDefinedTypes () - .SelectMany (t => GetCustomAttributeCtorValues (t, nameof (KeptReferenceAttribute))) - .Select (ReduceAssemblyFileNameOrNameToNameOnly) - .ToArray (); - - /* - - The test case will always need to have at least 1 reference. - - Forcing all tests to define their expected references seems tedious - - Given the above, let's assume that when no [KeptReference] attributes are present, - the test case does not want to make any assertions regarding references. - - Once 1 kept reference attribute is used, the test will need to define all of of it's expected references - */ - if (expected.Length == 0) - return; - - var actual = linked.MainModule.AssemblyReferences - .Select (name => name.Name) - .ToArray (); - - actual.Should ().BeEquivalentTo (expected); - } - - string? ReduceAssemblyFileNameOrNameToNameOnly (string? fileNameOrAssemblyName) - { - if (fileNameOrAssemblyName == null) - return null; - - if (fileNameOrAssemblyName.EndsWith (".dll") || fileNameOrAssemblyName.EndsWith (".exe") || fileNameOrAssemblyName.EndsWith (".winmd")) - return System.IO.Path.GetFileNameWithoutExtension (fileNameOrAssemblyName); - - // It must already be just the assembly name - return fileNameOrAssemblyName; - } - - void VerifyResources (AssemblyDefinition original, AssemblyDefinition linked) - { - var expectedResourceNames = original.MainModule.AllDefinedTypes () - .SelectMany (t => GetCustomAttributeCtorValues (t, nameof (KeptResourceAttribute))) - .ToList (); - - foreach (var resource in linked.MainModule.Resources) { - if (!expectedResourceNames.Remove (resource.Name)) - Assert.True (false, $"Resource '{resource.Name}' should be removed."); - - EmbeddedResource embeddedResource = (EmbeddedResource) resource; - - var expectedResource = (EmbeddedResource) original.MainModule.Resources.First (r => r.Name == resource.Name); - - embeddedResource.GetResourceData ().Should ().BeEquivalentTo (expectedResource.GetResourceData (), $"Resource '{resource.Name}' data doesn't match."); - } - - if (expectedResourceNames.Count > 0) { - Assert.True (false, $"Resource '{expectedResourceNames.First ()}' should be kept."); - } - } - - void VerifyExportedTypes (AssemblyDefinition original, AssemblyDefinition linked) - { - var expectedTypes = original.MainModule.AllDefinedTypes () - .SelectMany (t => GetCustomAttributeCtorValues (t, nameof (KeptExportedTypeAttribute)).Select (l => l?.FullName ?? "")).ToArray (); - - linked.MainModule.ExportedTypes.Select (l => l.FullName).Should ().BeEquivalentTo (expectedTypes); - } - - protected virtual void VerifyPseudoAttributes (MethodDefinition src, MethodDefinition linked) - { - var expected = (MethodAttributes) GetExpectedPseudoAttributeValue (src, (uint) src.Attributes); - linked.Attributes.Should ().Be (expected, $"Method `{src}' pseudo attributes did not match expected"); - } - - protected virtual void VerifyPseudoAttributes (TypeDefinition src, TypeDefinition linked) - { - var expected = (TypeAttributes) GetExpectedPseudoAttributeValue (src, (uint) src.Attributes); - linked.Attributes.Should ().Be (expected, $"Type `{src}' pseudo attributes did not match expected"); - } - - protected virtual void VerifyPseudoAttributes (FieldDefinition src, FieldDefinition linked) - { - var expected = (FieldAttributes) GetExpectedPseudoAttributeValue (src, (uint) src.Attributes); - linked.Attributes.Should ().Be (expected, $"Field `{src}' pseudo attributes did not match expected"); - } - - protected virtual void VerifyPseudoAttributes (PropertyDefinition src, PropertyDefinition linked) - { - var expected = (PropertyAttributes) GetExpectedPseudoAttributeValue (src, (uint) src.Attributes); - linked.Attributes.Should ().Be (expected, $"Property `{src}' pseudo attributes did not match expected"); - } - - protected virtual void VerifyPseudoAttributes (EventDefinition src, EventDefinition linked) - { - var expected = (EventAttributes) GetExpectedPseudoAttributeValue (src, (uint) src.Attributes); - linked.Attributes.Should ().Be (expected, $"Event `{src}' pseudo attributes did not match expected"); - } - - protected virtual void VerifyCustomAttributes (ICustomAttributeProvider src, ICustomAttributeProvider linked) - { - var expectedAttrs = GetExpectedAttributes (src).ToList (); - var linkedAttrs = FilterLinkedAttributes (linked).ToList (); - - linkedAttrs.Should ().BeEquivalentTo (expectedAttrs, $"Custom attributes on `{src}' are not matching"); - } - - protected virtual void VerifySecurityAttributes (ICustomAttributeProvider src, ISecurityDeclarationProvider linked) - { - var expectedAttrs = GetCustomAttributeCtorValues (src, nameof (KeptSecurityAttribute)) - .Select (attr => attr?.ToString () ?? "") - .ToList (); - - var linkedAttrs = FilterLinkedSecurityAttributes (linked).ToList (); - - linkedAttrs.Should ().BeEquivalentTo (expectedAttrs, $"Security attributes on `{src}' are not matching"); - } - - protected virtual void VerifyArrayInitializers (MethodDefinition src, MethodDefinition linked) - { - var expectedIndicies = GetCustomAttributeCtorValues (src, nameof (KeptInitializerData)) - .Cast () - .ToArray (); - - var expectKeptAll = src.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptInitializerData) && !attr.HasConstructorArguments); - - if (expectedIndicies.Length == 0 && !expectKeptAll) - return; - - if (!src.HasBody) - Assert.True (false, $"`{nameof (KeptInitializerData)}` cannot be used on methods that don't have bodies"); - - var srcImplementationDetails = src.Module.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("")); - - if (srcImplementationDetails == null) { - Assert.True (false, "Could not locate in the original assembly. Does your test use initializers?"); - return; - } - - var linkedImplementationDetails = linked.Module.Types.FirstOrDefault (t => string.IsNullOrEmpty (t.Namespace) && t.Name.StartsWith ("")); - - if (linkedImplementationDetails == null) { - Assert.True (false, "Could not locate in the linked assembly"); - return; - } - - var possibleInitializerFields = src.Body.Instructions - .Where (ins => IsLdtokenOnPrivateImplementationDetails (srcImplementationDetails, ins)) - .Select (ins => ((FieldReference) ins.Operand).Resolve ()) - .ToArray (); - - if (possibleInitializerFields.Length == 0) - Assert.True (false, $"`{src}` does not make use of any initializers"); - - if (expectKeptAll) { - foreach (var srcField in possibleInitializerFields) { - var linkedField = linkedImplementationDetails.Fields.FirstOrDefault (f => f.InitialValue.SequenceEqual (srcField.InitialValue)); - VerifyInitializerField (srcField, linkedField); - } - } else { - foreach (var index in expectedIndicies) { - if (index < 0 || index > possibleInitializerFields.Length) - Assert.True (false, $"Invalid expected index `{index}` in {src}. Value must be between 0 and {expectedIndicies.Length}"); - - var srcField = possibleInitializerFields[index]; - var linkedField = linkedImplementationDetails.Fields.FirstOrDefault (f => f.InitialValue.SequenceEqual (srcField.InitialValue)); - - VerifyInitializerField (srcField, linkedField); - } - } - } - - void VerifyInitializerField (FieldDefinition src, FieldDefinition? linked) - { - VerifyFieldKept (src, linked); - verifiedGeneratedFields.Add (linked!.FullName); - linkedMembers.Remove (linked.FullName); - VerifyTypeDefinitionKept (src.FieldType.Resolve (), linked.FieldType.Resolve ()); - linkedMembers.Remove (linked.FieldType.FullName); - linkedMembers.Remove (linked.DeclaringType.FullName); - verifiedGeneratedTypes.Add (linked.DeclaringType.FullName); - } - - static bool IsLdtokenOnPrivateImplementationDetails (TypeDefinition privateImplementationDetails, Instruction instruction) - { - if (instruction.OpCode.Code == Code.Ldtoken && instruction.Operand is FieldReference field) { - return field.DeclaringType.Resolve () == privateImplementationDetails; - } - - return false; - } - - protected static IEnumerable GetExpectedAttributes (ICustomAttributeProvider original) - { - foreach (var expectedAttrs in GetCustomAttributeCtorValues (original, nameof (KeptAttributeAttribute))) - yield return expectedAttrs?.ToString (); - - // The name of the generated fixed buffer type is a little tricky. - // Some versions of csc name it `e__FixedBuffer0` - // while mcs and other versions of csc name it `__FixedBuffer0` - if (original is TypeDefinition srcDefinition && srcDefinition.Name.Contains ("__FixedBuffer")) { - var name = srcDefinition.Name.Substring (1, srcDefinition.Name.IndexOf ('>') - 1); - var fixedField = srcDefinition.DeclaringType.Fields.FirstOrDefault (f => f.Name == name); - if (fixedField == null) - Assert.True (false, $"Could not locate original fixed field for {srcDefinition}"); - - foreach (var additionalExpectedAttributesFromFixedField in GetCustomAttributeCtorValues (fixedField!, nameof (KeptAttributeOnFixedBufferTypeAttribute))) - yield return additionalExpectedAttributesFromFixedField?.ToString (); - - } - } - - /// - /// Filters out some attributes that should not be taken into consideration when checking the linked result against the expected result - /// - /// - /// - protected virtual IEnumerable FilterLinkedAttributes (ICustomAttributeProvider linked) - { - foreach (var attr in linked.CustomAttributes) { - switch (attr.AttributeType.FullName) { - case "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute": - case "System.Runtime.CompilerServices.CompilerGeneratedAttribute": - continue; - - // When mcs is used to compile the test cases, backing fields end up with this attribute on them - case "System.Diagnostics.DebuggerBrowsableAttribute": - continue; - - // When compiling with roslyn, assemblies get the DebuggableAttribute by default. - case "System.Diagnostics.DebuggableAttribute": - continue; - - case "System.Runtime.CompilerServices.CompilationRelaxationsAttribute": - if (linked is AssemblyDefinition) - continue; - break; - } - - yield return attr.AttributeType.FullName; - } - } - - protected virtual IEnumerable FilterLinkedSecurityAttributes (ISecurityDeclarationProvider linked) - { - return linked.SecurityDeclarations - .SelectMany (d => d.SecurityAttributes) - .Select (attr => attr.AttributeType.ToString ()); - } - - void VerifyFixedBufferFields (TypeDefinition src, TypeDefinition linked) - { - var fields = src.Fields.Where (f => f.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (KeptFixedBufferAttribute))); - - foreach (var field in fields) { - // The name of the generated fixed buffer type is a little tricky. - // Some versions of csc name it `e__FixedBuffer0` - // while mcs and other versions of csc name it `__FixedBuffer0` - var originalCompilerGeneratedBufferType = src.NestedTypes.FirstOrDefault (t => t.FullName.Contains ($"<{field.Name}>") && t.FullName.Contains ("__FixedBuffer")); - if (originalCompilerGeneratedBufferType == null) { - Assert.True (false, $"Could not locate original compiler generated fixed buffer type for field {field}"); - return; - } - - var linkedCompilerGeneratedBufferType = linked.NestedTypes.FirstOrDefault (t => t.Name == originalCompilerGeneratedBufferType.Name); - if (linkedCompilerGeneratedBufferType == null) { - Assert.True (false, $"Missing expected type {originalCompilerGeneratedBufferType}"); - return; - } - - // Have to verify the field before the type - var originalElementField = originalCompilerGeneratedBufferType.Fields.FirstOrDefault (); - if (originalElementField == null) { - Assert.True (false, $"Could not locate original compiler generated FixedElementField on {originalCompilerGeneratedBufferType}"); - return; - } - - var linkedField = linkedCompilerGeneratedBufferType?.Fields.FirstOrDefault (); - VerifyFieldKept (originalElementField, linkedField); - verifiedGeneratedFields.Add (originalElementField.FullName); - linkedMembers.Remove (linkedField!.FullName); - - VerifyTypeDefinitionKept (originalCompilerGeneratedBufferType, linkedCompilerGeneratedBufferType); - verifiedGeneratedTypes.Add (originalCompilerGeneratedBufferType.FullName); - } - } - - void VerifyDelegateBackingFields (TypeDefinition src, TypeDefinition linked) - { - var expectedFieldNames = GetCustomAttributeCtorValues (src, nameof (KeptDelegateCacheFieldAttribute)) - .Select (unique => $"<>f__mg$cache{unique}") - .ToList (); - - if (expectedFieldNames.Count == 0) - return; - - foreach (var srcField in src.Fields) { - if (!expectedFieldNames.Contains (srcField.Name)) - continue; - - var linkedField = linked?.Fields.FirstOrDefault (l => l.Name == srcField.Name); - VerifyFieldKept (srcField, linkedField); - verifiedGeneratedFields.Add (srcField.FullName); - linkedMembers.Remove (srcField.FullName); - } - } - - void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterProvider linked) - { - Assert.Equal (src.HasGenericParameters, linked.HasGenericParameters); - if (src.HasGenericParameters) { - for (int i = 0; i < src.GenericParameters.Count; ++i) { - // TODO: Verify constraints - var srcp = src.GenericParameters[i]; - var lnkp = linked.GenericParameters[i]; - VerifyCustomAttributes (srcp, lnkp); - - if (checkNames) { - if (srcp.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (RemovedNameValueAttribute))) { - string name = (src.GenericParameterType == GenericParameterType.Method ? "!!" : "!") + srcp.Position; - lnkp.Name.Should ().Be (name, "Expected empty generic parameter name"); - } else { - lnkp.Name.Should ().Be (srcp.Name, "Mismatch in generic parameter name"); - } - } - } - } - } - - void VerifyParameters (IMethodSignature src, IMethodSignature linked) - { - Assert.Equal (src.HasParameters, linked.HasParameters); - if (src.HasParameters) { - for (int i = 0; i < src.Parameters.Count; ++i) { - var srcp = src.Parameters[i]; - var lnkp = linked.Parameters[i]; - - VerifyCustomAttributes (srcp, lnkp); - - if (checkNames) { - if (srcp.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (RemovedNameValueAttribute))) - lnkp.Name.Should ().BeEmpty ("Expected empty parameter name"); - else - lnkp.Name.Should ().Be (srcp.Name, "Mismatch in parameter name"); - } - } - } - } - - protected virtual bool ShouldMethodBeKept (MethodDefinition method) - { - var srcSignature = method.GetSignature (); - return ShouldBeKept (method, srcSignature) || method.DeclaringType.Module.EntryPoint == method; - } - - protected virtual bool ShouldBeKept (T member, string? signature = null) where T : MemberReference, ICustomAttributeProvider - { - if (member.HasAttribute (nameof (KeptAttribute))) - return true; - - ICustomAttributeProvider cap = (ICustomAttributeProvider) member.DeclaringType; - if (cap == null) - return false; - - return GetCustomAttributeCtorValues (cap, nameof (KeptMemberAttribute)).Any (a => a == (signature ?? member.Name)); - } - - protected static uint GetExpectedPseudoAttributeValue (ICustomAttributeProvider provider, uint sourceValue) - { - var removals = provider.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (RemovedPseudoAttributeAttribute)).ToArray (); - var adds = provider.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (AddedPseudoAttributeAttribute)).ToArray (); - - return removals.Aggregate (sourceValue, (accum, item) => accum & ~(uint) item.ConstructorArguments[0].Value) | - adds.Aggregate ((uint) 0, (acum, item) => acum | (uint) item.ConstructorArguments[0].Value); - } - - protected static IEnumerable GetCustomAttributeCtorValues (ICustomAttributeProvider provider, string attributeName) where T : class - { - return provider.CustomAttributes. - Where (w => w.AttributeType.Name == attributeName && w.Constructor.Parameters.Count == 1). - Select (l => l.ConstructorArguments[0].Value as T); - } - - protected static IEnumerable GetStringOrTypeArrayAttributeValue (CustomAttribute attribute) - { - foreach (var arg in (CustomAttributeArgument[]) attribute.ConstructorArguments[0].Value) { - if (arg.Value is TypeReference tRef) - yield return tRef.ToString (); - else - yield return (string) arg.Value; - } - } - - protected static IEnumerable? GetStringArrayAttributeValue (CustomAttribute attribute) - { - return ((CustomAttributeArgument[]) attribute.ConstructorArguments[0].Value)?.Select (arg => arg.Value.ToString ()!); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/BaseMetadataProvider.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/BaseMetadataProvider.cs deleted file mode 100644 index b136da80846b4..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/BaseMetadataProvider.cs +++ /dev/null @@ -1,96 +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.Linq; -using Mono.Cecil; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCases; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public abstract class BaseMetadataProvider - { - protected readonly TestCase _testCase; - protected readonly TypeDefinition _testCaseTypeDefinition; - - protected BaseMetadataProvider (TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition) - { - _testCase = testCase; - // The test case types are never nested so we don't need to worry about that - _testCaseTypeDefinition = fullTestCaseAssemblyDefinition.MainModule.GetType (_testCase.ReconstructedFullTypeName); - - if (_testCaseTypeDefinition == null) - throw new InvalidOperationException ($"Could not find the type definition for {_testCase.Name} in {_testCase.SourceFile}"); - } - - protected T? GetOptionAttributeValue (string attributeName, T? defaultValue) - { - var attribute = _testCaseTypeDefinition.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == attributeName); - if (attribute != null) - return (T?) attribute.ConstructorArguments.First ().Value; - - return defaultValue; - } - - protected NPath MakeSourceTreeFilePathAbsolute (string value) - { - return _testCase.SourceFile.Parent.Combine (value); - } - - protected SourceAndDestinationPair GetSourceAndRelativeDestinationValue (CustomAttribute attribute) - { - var fullSource = SourceFileForAttributeArgumentValue (attribute.ConstructorArguments.First ().Value); - var destinationFileName = (string) attribute.ConstructorArguments[1].Value; - return new SourceAndDestinationPair { - Source = fullSource, - DestinationFileName = string.IsNullOrEmpty (destinationFileName) ? fullSource.FileName : destinationFileName - }; - } - - - protected virtual NPath SourceFileForAttributeArgumentValue (object value) - { - if (value is TypeReference valueAsTypeRef) { - // Use the parent type for locating the source file - var parentType = ParentMostType (valueAsTypeRef); - var pathRelativeToAssembly = $"{parentType.FullName.Substring (parentType.Module.Name.Length - 3).Replace ('.', '/')}.cs".ToNPath (); - var pathElements = pathRelativeToAssembly.Elements.ToArray (); - var topMostDirectoryName = pathElements[0]; - var topMostDirectory = _testCase.SourceFile.RecursiveParents.Reverse ().FirstOrDefault (d => !d.IsRoot && d.FileName == topMostDirectoryName); - - if (topMostDirectory == null) { - // Before giving up, try and detect the naming scheme for tests that use a dot in the top level directory name. - // Ex: - // Attributes.Debugger - // + 1 because the file name is one of the elements - if (pathElements.Length >= 3) { - topMostDirectoryName = $"{pathElements[0]}.{pathElements[1]}"; - topMostDirectory = _testCase.SourceFile.RecursiveParents.Reverse ().FirstOrDefault (d => !d.IsRoot && d.FileName == topMostDirectoryName); - pathRelativeToAssembly = topMostDirectoryName.ToNPath ().Combine (pathElements.Skip (2).Aggregate (new NPath (string.Empty), (path, s) => path.Combine (s))); - } - - if (topMostDirectory == null) - throw new ArgumentException ($"Unable to locate the source file for type {valueAsTypeRef}. Could not locate directory {topMostDirectoryName}. Ensure the type name matches the file name. And the namespace match the directory structure on disk"); - } - - var fullPath = topMostDirectory.Parent.Combine (pathRelativeToAssembly); - - if (!fullPath.Exists ()) - throw new ArgumentException ($"Unable to locate the source file for type {valueAsTypeRef}. Expected {fullPath}. Ensure the type name matches the file name. And the namespace match the directory structure on disk"); - - return fullPath; - } - - return MakeSourceTreeFilePathAbsolute (value.ToString ()!); - } - - static TypeReference ParentMostType (TypeReference type) - { - if (!type.IsNested) - return type; - - return ParentMostType (type.DeclaringType); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs deleted file mode 100644 index 852576c73dfa0..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/CompilerOptions.cs +++ /dev/null @@ -1,20 +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 Mono.Linker.Tests.Extensions; - -#nullable disable - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class CompilerOptions - { - public NPath OutputPath; - public NPath[] SourceFiles; - public string[] Defines; - public NPath[] References; - public NPath[] Resources; - public string[] AdditionalArguments; - public string CompilerToUse; - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs deleted file mode 100644 index 7ca189d9befbd..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ExpectationsProvider.cs +++ /dev/null @@ -1,26 +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 Mono.Cecil; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Metadata; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public static class ExpectationsProvider - { - - public static bool IsAssemblyAssertion (CustomAttribute attr) - { - return attr.AttributeType.Name == nameof (KeptAssemblyAttribute) || - attr.AttributeType.Name == nameof (RemovedAssemblyAttribute) || - attr.AttributeType.Name == nameof (SetupLinkerActionAttribute) || - attr.AttributeType.Name == nameof (SetupLinkerTrimModeAttribute); - } - - public static bool IsSymbolAssertion (CustomAttribute attr) - { - return attr.AttributeType.Name == nameof (KeptSymbolsAttribute) || attr.AttributeType.Name == nameof (RemovedSymbolsAttribute); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs deleted file mode 100644 index 108e065098add..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/FormattingUtils.cs +++ /dev/null @@ -1,64 +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.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public static class FormattingUtils - { - public static string FormatSequenceCompareFailureMessage (IEnumerable actual, IEnumerable expected) - { - var builder = new StringBuilder (); - builder.AppendLine ("---------------"); - builder.AppendLine ($"Expected/Original (Total : {expected.Count ()})"); - builder.AppendLine ("---------------"); - // Format in a quoted array form for easier copying into a expected sequence attribute - builder.AppendLine (expected.Select (c => $"\"{c}\",").AggregateWithNewLine ()); - builder.AppendLine ("---------------"); - builder.AppendLine ($"Actual/Linked (Total : {actual.Count ()})"); - builder.AppendLine ("---------------"); - // Format in a quoted array form for easier copying into a expected sequence attribute - builder.AppendLine (actual.Select (c => $"\"{c}\",").AggregateWithNewLine ()); - builder.AppendLine ("---------------"); - return builder.ToString (); - } - - public static string FormatSequenceCompareFailureMessage2 (IEnumerable actual, IEnumerable expected, IEnumerable original) - { - var builder = new StringBuilder (); - builder.AppendLine ("---------------"); - builder.AppendLine ($"Expected (Total : {expected.Count ()})"); - builder.AppendLine ("---------------"); - // Format in a quoted array form for easier copying into a expected sequence attribute - builder.AppendLine (expected.Select (c => $"\"{c}\",").AggregateWithNewLine ()); - builder.AppendLine ("---------------"); - builder.AppendLine ($"Actual/Linked (Total : {actual.Count ()})"); - builder.AppendLine ("---------------"); - // Format in a quoted array form for easier copying into a expected sequence attribute - builder.AppendLine (actual.Select (c => $"\"{c}\",").AggregateWithNewLine ()); - builder.AppendLine ("---------------"); - builder.AppendLine ($"Original (Total : {original.Count ()})"); - builder.AppendLine ("---------------"); - // Format in a quoted array form for easier copying into a expected sequence attribute - builder.AppendLine (original.Select (c => $"\"{c}\",").AggregateWithNewLine ()); - builder.AppendLine ("---------------"); - return builder.ToString (); - } - - private static string AggregateWithNewLine (this IEnumerable elements) - { - return elements.AggregateWith (System.Environment.NewLine); - } - - private static string AggregateWith (this IEnumerable elements, string separator) - { - if (elements.Any ()) - return elements.Aggregate ((buff, s) => buff + separator + s); - - return string.Empty; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerDriver.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerDriver.cs deleted file mode 100644 index a0eff369ee98a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerDriver.cs +++ /dev/null @@ -1,137 +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.Reflection; -using System.Runtime.InteropServices; -using ILCompiler; -using ILLink.Shared.TrimAnalysis; -using Internal.IL; -using Internal.TypeSystem; -using Internal.TypeSystem.Ecma; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ILCompilerDriver - { - private const string DefaultSystemModule = "System.Private.CoreLib"; - - public void Trim (ILCompilerOptions options, ILogWriter logWriter) - { - ComputeDefaultOptions (out var targetOS, out var targetArchitecture); - var targetDetails = new TargetDetails (targetArchitecture, targetOS, TargetAbi.NativeAot); - CompilerTypeSystemContext typeSystemContext = - new CompilerTypeSystemContext (targetDetails, SharedGenericsMode.CanonicalReferenceTypes, DelegateFeature.All); - - typeSystemContext.InputFilePaths = options.InputFilePaths; - typeSystemContext.ReferenceFilePaths = options.ReferenceFilePaths; - typeSystemContext.SetSystemModule (typeSystemContext.GetModuleForSimpleName (DefaultSystemModule)); - - List inputModules = new List (); - foreach (var inputFile in typeSystemContext.InputFilePaths) { - EcmaModule module = typeSystemContext.GetModuleFromPath (inputFile.Value); - inputModules.Add (module); - } - - CompilationModuleGroup compilationGroup = new MultiFileSharedCompilationModuleGroup (typeSystemContext, inputModules); - - List compilationRoots = new List (); - EcmaModule? entrypointModule = null; - foreach (var inputFile in typeSystemContext.InputFilePaths) { - EcmaModule module = typeSystemContext.GetModuleFromPath (inputFile.Value); - - if (module.PEReader.PEHeaders.IsExe) { - if (entrypointModule != null) - throw new Exception ("Multiple EXE modules"); - entrypointModule = module; - } - - compilationRoots.Add (new ExportedMethodsRootProvider (module)); - } - - compilationRoots.Add (new MainMethodRootProvider (entrypointModule, CreateInitializerList (typeSystemContext, options))); - - ILProvider ilProvider = new NativeAotILProvider (); - - ilProvider = new FeatureSwitchManager (ilProvider, options.FeatureSwitches); - - Logger logger = new Logger (logWriter, isVerbose: true); - - UsageBasedMetadataManager metadataManager = new UsageBasedMetadataManager ( - compilationGroup, - typeSystemContext, - new NoMetadataBlockingPolicy (), - new ManifestResourceBlockingPolicy (options.FeatureSwitches), - logFile: null, - new NoStackTraceEmissionPolicy (), - new NoDynamicInvokeThunkGenerationPolicy (), - new FlowAnnotations (logger, ilProvider), - UsageBasedMetadataGenerationOptions.ReflectionILScanning, - logger, - Array.Empty> (), - Array.Empty (), - options.TrimAssemblies.ToArray ()); - - CompilationBuilder builder = new RyuJitCompilationBuilder (typeSystemContext, compilationGroup) - .UseILProvider (ilProvider) - .UseCompilationUnitPrefix(""); - - IILScanner scanner = builder.GetILScannerBuilder () - .UseCompilationRoots (compilationRoots) - .UseMetadataManager (metadataManager) - .UseParallelism (System.Diagnostics.Debugger.IsAttached ? 1 : -1) - .ToILScanner (); - - ILScanResults results = scanner.Scan (); - } - - public static void ComputeDefaultOptions (out TargetOS os, out TargetArchitecture arch) - { - if (RuntimeInformation.IsOSPlatform (OSPlatform.Windows)) - os = TargetOS.Windows; - else if (RuntimeInformation.IsOSPlatform (OSPlatform.Linux)) - os = TargetOS.Linux; - else if (RuntimeInformation.IsOSPlatform (OSPlatform.OSX)) - os = TargetOS.OSX; - else if (RuntimeInformation.IsOSPlatform (OSPlatform.FreeBSD)) - os = TargetOS.FreeBSD; - else - throw new NotImplementedException (); - - switch (RuntimeInformation.ProcessArchitecture) { - case Architecture.X86: - arch = TargetArchitecture.X86; - break; - case Architecture.X64: - arch = TargetArchitecture.X64; - break; - case Architecture.Arm: - arch = TargetArchitecture.ARM; - break; - case Architecture.Arm64: - arch = TargetArchitecture.ARM64; - break; - default: - throw new NotImplementedException (); - } - } - - private IReadOnlyCollection CreateInitializerList (CompilerTypeSystemContext context, ILCompilerOptions options) - { - List assembliesWithInitalizers = new List (); - - // Build a list of assemblies that have an initializer that needs to run before - // any user code runs. - foreach (string initAssemblyName in options.InitAssemblies) { - ModuleDesc assembly = context.ResolveAssembly (new AssemblyName (initAssemblyName), throwIfNotFound: true); - assembliesWithInitalizers.Add (assembly); - } - - var libraryInitializers = new LibraryInitializers (context, assembliesWithInitalizers); - - List initializerList = new List (libraryInitializers.LibraryInitializerMethods); - return initializerList; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptions.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptions.cs deleted file mode 100644 index 7bba7ae4de334..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptions.cs +++ /dev/null @@ -1,16 +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.Collections.Generic; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ILCompilerOptions - { - public Dictionary InputFilePaths = new Dictionary (); - public Dictionary ReferenceFilePaths = new Dictionary (); - public List InitAssemblies = new List (); - public List TrimAssemblies = new List (); - public Dictionary FeatureSwitches = new Dictionary (); - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptionsBuilder.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptionsBuilder.cs deleted file mode 100644 index 98f0ee4351ef1..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerOptionsBuilder.cs +++ /dev/null @@ -1,253 +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.IO; -using Mono.Linker.Tests.Extensions; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ILCompilerOptionsBuilder - { - //public TrimmerOptions Options { get; } = new(); - private readonly TestCaseMetadataProvider _metadataProvider; - - public readonly ILCompilerOptions Options; - - public ILCompilerOptionsBuilder (TestCaseMetadataProvider metadataProvider) - { - Options = new ILCompilerOptions (); - _metadataProvider = metadataProvider; - - string runtimeBinDir = (string) AppContext.GetData ("Mono.Linker.Tests.RuntimeBinDirectory")!; - AppendExpandedPaths (Options.ReferenceFilePaths, Path.Combine (runtimeBinDir, "aotsdk", "*.dll")); - - string runtimePackDir = (string) AppContext.GetData ("Mono.Linker.Tests.MicrosoftNetCoreAppRuntimePackDirectory")!; - if (!Directory.Exists (runtimePackDir) && runtimePackDir.Contains ("Debug")) { - // Frequently we'll have a Debug runtime and Release libraries, which actually produces a Release runtime pack - // but from within VS we're see Debug everything. So if the runtime pack directory doesn't exist - // try the Release path (simple string replace) - string candidate = runtimePackDir.Replace ("Debug", "Release"); - if (Directory.Exists (candidate)) - runtimePackDir = candidate; - } - AppendExpandedPaths (Options.ReferenceFilePaths, Path.Combine (runtimePackDir, "*.dll")); - - Options.InitAssemblies.Add ("System.Private.CoreLib"); - Options.InitAssemblies.Add ("System.Private.StackTraceMetadata"); - Options.InitAssemblies.Add ("System.Private.TypeLoader"); - Options.InitAssemblies.Add ("System.Private.Reflection.Execution"); - - Options.FeatureSwitches.Add ("System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization", false); - Options.FeatureSwitches.Add ("System.Resources.ResourceManager.AllowCustomResourceTypes", false); - Options.FeatureSwitches.Add ("System.Linq.Expressions.CanCompileToIL", false); - Options.FeatureSwitches.Add ("System.Linq.Expressions.CanEmitObjectArrayDelegate", false); - Options.FeatureSwitches.Add ("System.Linq.Expressions.CanCreateArbitraryDelegates", false); - } - - public virtual void AddSearchDirectory (NPath directory) - { - } - - public virtual void AddReference (NPath path) - { - AppendExpandedPaths (Options.ReferenceFilePaths, path.ToString ()); - } - - public virtual void AddOutputDirectory (NPath directory) - { - } - - public virtual void AddLinkXmlFile (string file) - { - } - - public virtual void AddResponseFile (NPath path) - { - } - - public virtual void AddTrimMode (string value) - { - } - - public virtual void AddDefaultAction (string value) - { - } - - public virtual void AddLinkAssembly (string fileName) - { - Options.TrimAssemblies.Add (fileName); - } - - public virtual void LinkFromAssembly (string fileName) - { - AppendExpandedPaths (Options.InputFilePaths, fileName); - } - - public virtual void LinkFromPublicAndFamily (string fileName) - { - } - - public virtual void IgnoreDescriptors (bool value) - { - } - - public virtual void IgnoreSubstitutions (bool value) - { - } - - public virtual void IgnoreLinkAttributes (bool value) - { - } - - public virtual void AddIl8n (string value) - { - } - - public virtual void AddKeepTypeForwarderOnlyAssemblies (string value) - { - } - - public virtual void AddLinkSymbols (string value) - { - } - - public virtual void AddKeepDebugMembers (string value) - { - } - - public virtual void AddAssemblyAction (string action, string assembly) - { - } - - public virtual void AddSkipUnresolved (bool skipUnresolved) - { - } - - public virtual void AddStripDescriptors (bool stripDescriptors) - { - } - - public virtual void AddStripSubstitutions (bool stripSubstitutions) - { - } - - public virtual void AddStripLinkAttributes (bool stripLinkAttributes) - { - } - - public virtual void AddSubstitutions (string file) - { - } - - public virtual void AddLinkAttributes (string file) - { - } - - public virtual void AddAdditionalArgument (string flag, string[] values) - { - if (flag == "--feature") { - Options.FeatureSwitches.Add (values[0], bool.Parse (values[1])); - } - } - - public virtual void ProcessTestInputAssembly (NPath inputAssemblyPath) - { - if (_metadataProvider.LinkPublicAndFamily ()) - LinkFromPublicAndFamily (inputAssemblyPath.ToString ()); - else - LinkFromAssembly (inputAssemblyPath.ToString ()); - } - - public virtual void ProcessOptions (TestCaseLinkerOptions options) - { - if (options.TrimMode != null) - AddTrimMode (options.TrimMode); - - if (options.DefaultAssembliesAction != null) - AddDefaultAction (options.DefaultAssembliesAction); - - if (options.AssembliesAction != null) { - foreach (var (action, assembly) in options.AssembliesAction) - AddAssemblyAction (action, assembly); - } - - // Honoring descriptors causes a ton of stuff to be preserved. That's good for normal use cases, but for - // our test cases that pollutes the results - IgnoreDescriptors (options.IgnoreDescriptors); - - IgnoreSubstitutions (options.IgnoreSubstitutions); - - IgnoreLinkAttributes (options.IgnoreLinkAttributes); - -#if !NETCOREAPP - if (!string.IsNullOrEmpty (options.Il8n)) - AddIl8n (options.Il8n); -#endif - - if (!string.IsNullOrEmpty (options.KeepTypeForwarderOnlyAssemblies)) - AddKeepTypeForwarderOnlyAssemblies (options.KeepTypeForwarderOnlyAssemblies); - - if (!string.IsNullOrEmpty (options.LinkSymbols)) - AddLinkSymbols (options.LinkSymbols); - - if (!string.IsNullOrEmpty (options.KeepDebugMembers)) - AddKeepDebugMembers (options.KeepDebugMembers); - - AddSkipUnresolved (options.SkipUnresolved); - - AddStripDescriptors (options.StripDescriptors); - - AddStripSubstitutions (options.StripSubstitutions); - - AddStripLinkAttributes (options.StripLinkAttributes); - - foreach (var descriptor in options.Descriptors) - AddLinkXmlFile (descriptor); - - foreach (var substitutions in options.Substitutions) - AddSubstitutions (substitutions); - - foreach (var attributeDefinition in options.LinkAttributes) - AddLinkAttributes (attributeDefinition); - - // A list of expensive optimizations which should not run by default - AddAdditionalArgument ("--disable-opt", new[] { "ipconstprop" }); - - // Unity uses different argument format and needs to be able to translate to their format. In order to make that easier - // we keep the information in flag + values format for as long as we can so that this information doesn't have to be parsed out of a single string - foreach (var additionalArgument in options.AdditionalArguments) - AddAdditionalArgument (additionalArgument.Key, additionalArgument.Value); - } - - static void AppendExpandedPaths (Dictionary dictionary, string pattern) - { - bool empty = true; - - string directoryName = Path.GetDirectoryName (pattern)!; - string searchPattern = Path.GetFileName (pattern); - - if (directoryName == "") - directoryName = "."; - - if (Directory.Exists (directoryName)) { - foreach (string fileName in Directory.EnumerateFiles (directoryName, searchPattern)) { - string fullFileName = Path.GetFullPath (fileName); - - string simpleName = Path.GetFileNameWithoutExtension (fileName); - - if (!dictionary.ContainsKey (simpleName)) { - dictionary.Add (simpleName, fullFileName); - } - - empty = false; - } - } - - if (empty) { - throw new Exception ("No files matching " + pattern); - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerTestCaseResult.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerTestCaseResult.cs deleted file mode 100644 index 8fe4bfe8b8e71..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILCompilerTestCaseResult.cs +++ /dev/null @@ -1,31 +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 Mono.Linker.Tests.TestCasesRunner; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCases; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ILCompilerTestCaseResult - { - public readonly TestCase TestCase; - public readonly NPath InputAssemblyPath; - public readonly NPath ExpectationsAssemblyPath; - public readonly TestCaseSandbox Sandbox; - public readonly TestCaseMetadataProvider MetadataProvider; - public readonly ManagedCompilationResult CompilationResult; - public readonly TestLogWriter LogWriter; - - public ILCompilerTestCaseResult (TestCase testCase, NPath inputAssemblyPath, NPath expectationsAssemblyPath, TestCaseSandbox sandbox, TestCaseMetadataProvider metadataProvider, ManagedCompilationResult compilationResult, TestLogWriter logWriter) - { - TestCase = testCase; - InputAssemblyPath = inputAssemblyPath; - ExpectationsAssemblyPath = expectationsAssemblyPath; - Sandbox = sandbox; - MetadataProvider = metadataProvider; - CompilationResult = compilationResult; - LogWriter = logWriter; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILInputCompiler.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILInputCompiler.cs deleted file mode 100644 index 32973f050fa6e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ILInputCompiler.cs +++ /dev/null @@ -1,93 +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.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using Mono.Linker.Tests.Extensions; -using Xunit; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ILInputCompiler - { - public NPath Compile (CompilerOptions options) - { - var capturedOutput = new List (); - var process = new Process (); - SetupProcess (process, options); - process.StartInfo.RedirectStandardOutput = true; - process.OutputDataReceived += (sender, args) => capturedOutput.Add (args.Data!); - process.Start (); - process.BeginOutputReadLine (); - process.WaitForExit (); - - if (process.ExitCode != 0) { - Assert.True (false, $"Failed to compile IL assembly : {options.OutputPath}\n{capturedOutput.Aggregate ((buff, s) => buff + Environment.NewLine + s)}"); - } - - return options.OutputPath; - } - - protected virtual void SetupProcess (Process process, CompilerOptions options) - { - process.StartInfo.FileName = LocateIlasm ().ToString (); - process.StartInfo.Arguments = BuildArguments (options); - process.StartInfo.UseShellExecute = false; - process.StartInfo.CreateNoWindow = true; - process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; - } - - private string BuildArguments (CompilerOptions options) - { - var args = new StringBuilder (); -#if NETCOREAPP - args.Append (options.OutputPath.ExtensionWithDot == ".dll" ? "-dll" : "-exe"); - args.Append ($" -out:{options.OutputPath.InQuotes ()}"); -#else - args.Append (options.OutputPath.ExtensionWithDot == ".dll" ? "/dll" : "/exe"); - args.Append ($" /out:{options.OutputPath.InQuotes ()}"); -#endif - args.Append ($" {options.SourceFiles.Aggregate (string.Empty, (buff, file) => $"{buff} {file.InQuotes ()}")}"); - return args.ToString (); - } - - protected virtual NPath LocateIlasm () - { -#if NETCOREAPP - var extension = RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ? ".exe" : ""; - - // working directory is artifacts/bin/Mono.Linker.Tests// - var toolsDir = Path.Combine (Directory.GetCurrentDirectory (), "..", "..", "..", "..", "tools"); - - var ilasmPath = Path.GetFullPath (Path.Combine (toolsDir, "ilasm", $"ilasm{extension}")).ToNPath (); - if (ilasmPath.FileExists ()) - return ilasmPath; - - throw new InvalidOperationException ("ilasm not found at " + ilasmPath); -#else - return Environment.OSVersion.Platform == PlatformID.Win32NT ? LocateIlasmOnWindows () : "ilasm".ToNPath (); -#endif - } - - public static NPath LocateIlasmOnWindows () - { - if (Environment.OSVersion.Platform != PlatformID.Win32NT) - throw new InvalidOperationException ("This method should only be called on windows"); - - var possiblePath = RuntimeEnvironment.GetRuntimeDirectory ().ToNPath ().Combine ("ilasm.exe"); - if (possiblePath.FileExists ()) - return possiblePath; - - possiblePath = Environment.CurrentDirectory.ToNPath ().Combine ("ilasm.exe"); - if (possiblePath.FileExists ()) - return possiblePath; - - throw new InvalidOperationException ("Could not locate a ilasm.exe executable"); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/IgnoreTestException.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/IgnoreTestException.cs deleted file mode 100644 index 767bc07454fcb..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/IgnoreTestException.cs +++ /dev/null @@ -1,12 +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; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - internal class IgnoreTestException : Exception - { - public IgnoreTestException (string message) : base (message) { } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs deleted file mode 100644 index fe7aa4c767da1..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ManagedCompilationResult.cs +++ /dev/null @@ -1,20 +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 Mono.Linker.Tests.Extensions; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ManagedCompilationResult - { - public ManagedCompilationResult (NPath inputAssemblyPath, NPath expectationsAssemblyPath) - { - InputAssemblyPath = inputAssemblyPath; - ExpectationsAssemblyPath = expectationsAssemblyPath; - } - - public NPath InputAssemblyPath { get; } - - public NPath ExpectationsAssemblyPath { get; } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs deleted file mode 100644 index f99a06ad15062..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ObjectFactory.cs +++ /dev/null @@ -1,41 +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 Mono.Cecil; -using Mono.Linker.Tests.TestCases; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ObjectFactory - { - public virtual TestCaseSandbox CreateSandbox (TestCase testCase) - { - return new TestCaseSandbox (testCase); - } - - public virtual TestCaseCompiler CreateCompiler (TestCaseSandbox sandbox, TestCaseCompilationMetadataProvider metadataProvider) - { - return new TestCaseCompiler (sandbox, metadataProvider); - } - - public virtual ILCompilerDriver CreateTrimmer () - { - return new ILCompilerDriver (); - } - - public virtual TestCaseMetadataProvider CreateMetadataProvider (TestCase testCase, AssemblyDefinition expectationsAssemblyDefinition) - { - return new TestCaseMetadataProvider (testCase, expectationsAssemblyDefinition); - } - - public virtual TestCaseCompilationMetadataProvider CreateCompilationMetadataProvider (TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition) - { - return new TestCaseCompilationMetadataProvider (testCase, fullTestCaseAssemblyDefinition); - } - - public virtual ILCompilerOptionsBuilder CreateTrimmerOptionsBuilder (TestCaseMetadataProvider metadataProvider) - { - return new ILCompilerOptionsBuilder (metadataProvider); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/PathUtilities.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/PathUtilities.cs deleted file mode 100644 index 5fb2090ac65e3..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/PathUtilities.cs +++ /dev/null @@ -1,35 +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.IO; -using System.Runtime.CompilerServices; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public static class PathUtilities - { -#if NET7_0 - public const string TFMDirectoryName = "net7.0"; -#elif NET6_0 - public const string TFMDirectoryName = "net6.0"; -#elif NET5_0 - public const string TFMDirectoryName = "net5.0"; -#elif NETCOREAPP3_0 - public const string TFMDirectoryName = "netcoreapp3.0"; -#else -#error "Unknown TFM" -#endif - - public static string GetTestsSourceRootDirectory ([CallerFilePath] string? thisFile = null) => - Path.GetFullPath ((string) AppContext.GetData ("Mono.Linker.Tests.NativeAotDir")!); - - public static string GetTestAssemblyPath (string assemblyName) - { - var artifactsBinDirectory = (string) AppContext.GetData ("Mono.Linker.Tests.ArtifactsBinDir")!; - var targetArch = (string) AppContext.GetData ("Mono.Linker.Tests.TargetArchitecture")!; - var configuration = (string) AppContext.GetData ("Mono.Linker.Tests.Configuration")!; - return Path.GetFullPath (Path.Combine (artifactsBinDirectory, assemblyName, targetArch, configuration, $"{assemblyName}.dll")); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs deleted file mode 100644 index cd3a1c2eca251..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/ResultChecker.cs +++ /dev/null @@ -1,405 +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.IO; -using System.Linq; -using System.Reflection.Metadata.Ecma335; -using System.Reflection.PortableExecutable; -using System.Runtime.CompilerServices; -using System.Text; -using System.Text.RegularExpressions; -using FluentAssertions; -using ILCompiler; -using ILCompiler.Dataflow; -using ILCompiler.Logging; -using Mono.Linker.Tests.TestCasesRunner; -using Internal.TypeSystem; -using Mono.Cecil; -using Mono.Cecil.Cil; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Metadata; -using Mono.Linker.Tests.Extensions; -using Xunit; -using Mono.Linker.Tests.Cases.RequiresCapability; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class ResultChecker - { - readonly BaseAssemblyResolver _originalsResolver; - readonly ReaderParameters _originalReaderParameters; - readonly ReaderParameters _linkedReaderParameters; - - public ResultChecker () - : this (new TestCaseAssemblyResolver (), - new ReaderParameters { - SymbolReaderProvider = new DefaultSymbolReaderProvider (false) - }, - new ReaderParameters { - SymbolReaderProvider = new DefaultSymbolReaderProvider (false) - }) - { - } - - public ResultChecker (BaseAssemblyResolver originalsResolver, - ReaderParameters originalReaderParameters, ReaderParameters linkedReaderParameters) - { - _originalsResolver = originalsResolver; - _originalReaderParameters = originalReaderParameters; - _linkedReaderParameters = linkedReaderParameters; - } - - public virtual void Check (ILCompilerTestCaseResult trimmedResult) - { - InitializeResolvers (trimmedResult); - - try { - var original = ResolveOriginalsAssembly (trimmedResult.ExpectationsAssemblyPath.FileNameWithoutExtension); - AdditionalChecking (trimmedResult, original); - } finally { - _originalsResolver.Dispose (); - } - } - - void InitializeResolvers (ILCompilerTestCaseResult linkedResult) - { - _originalsResolver.AddSearchDirectory (linkedResult.ExpectationsAssemblyPath.Parent.ToString ()); - } - - protected AssemblyDefinition ResolveOriginalsAssembly (string assemblyName) - { - var cleanAssemblyName = assemblyName; - if (assemblyName.EndsWith (".exe") || assemblyName.EndsWith (".dll")) - cleanAssemblyName = Path.GetFileNameWithoutExtension (assemblyName); - return _originalsResolver.Resolve (new AssemblyNameReference (cleanAssemblyName, null), _originalReaderParameters); - } - - protected virtual void AdditionalChecking (ILCompilerTestCaseResult linkResult, AssemblyDefinition original) - { - bool checkRemainingErrors = !HasAttribute (original.MainModule.GetType (linkResult.TestCase.ReconstructedFullTypeName), nameof (SkipRemainingErrorsValidationAttribute)); - VerifyLoggedMessages (original, linkResult.LogWriter, checkRemainingErrors); - } - - static bool IsProducedByNativeAOT (CustomAttribute attr) - { - var producedBy = attr.GetPropertyValue ("ProducedBy"); - return producedBy is null ? true : ((ProducedBy) producedBy).HasFlag (ProducedBy.NativeAot); - } - - static IEnumerable GetAttributeProviders (AssemblyDefinition assembly) - { - foreach (var testType in assembly.AllDefinedTypes ()) { - foreach (var provider in testType.AllMembers ()) - yield return provider; - - yield return testType; - } - - foreach (var module in assembly.Modules) - yield return module; - - yield return assembly; - } - - void VerifyLoggedMessages (AssemblyDefinition original, TestLogWriter logger, bool checkRemainingErrors) - { - List loggedMessages = logger.GetLoggedMessages (); - List<(IMemberDefinition, CustomAttribute)> expectedNoWarningsAttributes = new List<(IMemberDefinition, CustomAttribute)> (); - foreach (var attrProvider in GetAttributeProviders (original)) { - if (attrProvider.ToString() is String mystring && mystring.Contains ("RequiresInCompilerGeneratedCode/SuppressInLambda")) - Debug.WriteLine ("Print"); - foreach (var attr in attrProvider.CustomAttributes) { - if (!IsProducedByNativeAOT (attr)) - continue; - - switch (attr.AttributeType.Name) { - - case nameof (LogContainsAttribute): { - var expectedMessage = (string) attr.ConstructorArguments[0].Value; - - List matchedMessages; - if ((bool) attr.ConstructorArguments[1].Value) - matchedMessages = loggedMessages.Where (m => Regex.IsMatch (m.ToString (), expectedMessage)).ToList (); - else - matchedMessages = loggedMessages.Where (m => MessageTextContains (m.ToString (), expectedMessage)).ToList (); ; - Assert.True ( - matchedMessages.Count > 0, - $"Expected to find logged message matching `{expectedMessage}`, but no such message was found.{Environment.NewLine}Logged messages:{Environment.NewLine}{string.Join (Environment.NewLine, loggedMessages)}"); - - foreach (var matchedMessage in matchedMessages) - loggedMessages.Remove (matchedMessage); - } - break; - - case nameof (LogDoesNotContainAttribute): { - var unexpectedMessage = (string) attr.ConstructorArguments[0].Value; - foreach (var loggedMessage in loggedMessages) { - var isLogged = () => { - if ((bool) attr.ConstructorArguments[1].Value) - return !Regex.IsMatch (loggedMessage.ToString (), unexpectedMessage); - return !MessageTextContains (loggedMessage.ToString (), unexpectedMessage); - }; - - Assert.True ( - isLogged (), - $"Expected to not find logged message matching `{unexpectedMessage}`, but found:{Environment.NewLine}{loggedMessage.ToString ()}{Environment.NewLine}Logged messages:{Environment.NewLine}{string.Join (Environment.NewLine, loggedMessages)}"); - } - } - break; - - case nameof (ExpectedWarningAttribute): { - var expectedWarningCode = (string) attr.GetConstructorArgumentValue (0); - if (!expectedWarningCode.StartsWith ("IL")) { - Assert.Fail ($"The warning code specified in {nameof (ExpectedWarningAttribute)} must start with the 'IL' prefix. Specified value: '{expectedWarningCode}'."); - } - var expectedMessageContains = ((CustomAttributeArgument[]) attr.GetConstructorArgumentValue (1)).Select (a => (string) a.Value).ToArray (); - string fileName = (string) attr.GetPropertyValue ("FileName")!; - int? sourceLine = (int?) attr.GetPropertyValue ("SourceLine"); - int? sourceColumn = (int?) attr.GetPropertyValue ("SourceColumn"); - bool? isCompilerGeneratedCode = (bool?) attr.GetPropertyValue ("CompilerGeneratedCode"); - - int expectedWarningCodeNumber = int.Parse (expectedWarningCode.Substring (2)); - string? expectedOrigin = null; - bool expectedWarningFound = false; - - foreach (var loggedMessage in loggedMessages) { - if (loggedMessage.ToString ().Contains ("RequiresInCompilerGeneratedCode.SuppressInLambda")) { - Debug.WriteLine ("Print 2"); - } - - if (loggedMessage.Category != MessageCategory.Warning || loggedMessage.Code != expectedWarningCodeNumber) - continue; - - bool messageNotFound = false; - foreach (var expectedMessage in expectedMessageContains) { - if (!MessageTextContains (loggedMessage.Text, expectedMessage)) { - messageNotFound = true; - break; - } - } - if (messageNotFound) - continue; - - if (fileName != null) { - if (loggedMessage.Origin == null) - continue; - - var actualOrigin = loggedMessage.Origin.Value; - if (actualOrigin.FileName != null) { - // Note: string.Compare(string, StringComparison) doesn't exist in .NET Framework API set - if (actualOrigin.FileName.IndexOf (fileName, StringComparison.OrdinalIgnoreCase) < 0) - continue; - - if (sourceLine != null && loggedMessage.Origin?.SourceLine != sourceLine.Value) - continue; - - if (sourceColumn != null && loggedMessage.Origin?.SourceColumn != sourceColumn.Value) - continue; - } else { - // The warning was logged with member/ILoffset, so it didn't have line/column info filled - // but it will be computed from PDBs, so instead compare it in a string representation - if (expectedOrigin == null) { - expectedOrigin = fileName; - if (sourceLine.HasValue) { - expectedOrigin += "(" + sourceLine.Value; - if (sourceColumn.HasValue) - expectedOrigin += "," + sourceColumn.Value; - expectedOrigin += ")"; - } - } - - string actualOriginString = actualOrigin.ToString () ?? ""; - if (!actualOriginString.EndsWith (expectedOrigin, StringComparison.OrdinalIgnoreCase)) - continue; - } - } else if (isCompilerGeneratedCode == true) { - if (loggedMessage.Origin?.MemberDefinition is MethodDesc methodDesc) { - if (attrProvider is not IMemberDefinition expectedMember) - continue; - - string actualName = methodDesc.OwningType.ToString ().Replace("+", ".") + "." + methodDesc.Name; - if (actualName.Contains (expectedMember.DeclaringType.FullName.Replace ("/", ".")) && - actualName.Contains ("<" + expectedMember.Name + ">")) { - expectedWarningFound = true; - loggedMessages.Remove (loggedMessage); - break; - } - if (actualName.StartsWith (expectedMember.DeclaringType.FullName) && - actualName.Contains (".cctor") && (expectedMember is FieldDefinition || expectedMember is PropertyDefinition)) { - expectedWarningFound = true; - loggedMessages.Remove (loggedMessage); - break; - } - if (methodDesc.Name == ".ctor" && - methodDesc.OwningType.ToString () == expectedMember.FullName) { - expectedWarningFound = true; - loggedMessages.Remove (loggedMessage); - break; - } - } - continue; - } else { - if (LogMessageHasSameOriginMember (loggedMessage, attrProvider)) { - expectedWarningFound = true; - loggedMessages.Remove (loggedMessage); - break; - } - continue; - } - - expectedWarningFound = true; - loggedMessages.Remove (loggedMessage); - break; - } - - var expectedOriginString = fileName == null - ? GetExpectedOriginDisplayName (attrProvider) + ": " - : ""; - - Assert.True (expectedWarningFound, - $"Expected to find warning: {(fileName != null ? fileName + (sourceLine != null ? $"({sourceLine},{sourceColumn})" : "") + ": " : "")}" + - $"warning {expectedWarningCode}: {expectedOriginString}" + - $"and message containing {string.Join (" ", expectedMessageContains.Select (m => "'" + m + "'"))}, " + - $"but no such message was found.{Environment.NewLine}Logged messages:{Environment.NewLine}{string.Join (Environment.NewLine, loggedMessages)}"); - } - break; - - case nameof (ExpectedNoWarningsAttribute): - // Postpone processing of negative checks, to make it possible to mark some warnings as expected (will be removed from the list above) - // and then do the negative check on the rest. - var memberDefinition = attrProvider as IMemberDefinition; - Assert.NotNull (memberDefinition); - expectedNoWarningsAttributes.Add ((memberDefinition, attr)); - break; - } - } - } - - foreach ((var attrProvider, var attr) in expectedNoWarningsAttributes) { - var unexpectedWarningCode = attr.ConstructorArguments.Count == 0 ? null : (string) attr.GetConstructorArgumentValue (0); - if (unexpectedWarningCode != null && !unexpectedWarningCode.StartsWith ("IL")) { - Assert.Fail ($"The warning code specified in ExpectedNoWarnings attribute must start with the 'IL' prefix. Specified value: '{unexpectedWarningCode}'."); - } - - int? unexpectedWarningCodeNumber = unexpectedWarningCode == null ? null : int.Parse (unexpectedWarningCode.Substring (2)); - - MessageContainer? unexpectedWarningMessage = null; - foreach (var mc in logger.GetLoggedMessages ()) { - if (mc.Category != MessageCategory.Warning) - continue; - - if (unexpectedWarningCodeNumber != null && unexpectedWarningCodeNumber.Value != mc.Code) - continue; - - // This is a hacky way to say anything in the "subtree" of the attrProvider - if ((mc.Origin?.MemberDefinition is TypeSystemEntity member) && member.ToString ()?.Contains (attrProvider.FullName) != true) - continue; - - unexpectedWarningMessage = mc; - break; - } - - Assert.False (unexpectedWarningMessage.HasValue, - $"Unexpected warning found: {unexpectedWarningMessage}"); - } - - if (checkRemainingErrors) { - var remainingErrors = loggedMessages.Where (m => Regex.IsMatch (m.ToString (), @".*(error | warning): \d{4}.*")); - Assert.False (remainingErrors.Any (), $"Found unexpected errors:{Environment.NewLine}{string.Join (Environment.NewLine, remainingErrors)}"); - } - - bool LogMessageHasSameOriginMember (MessageContainer mc, ICustomAttributeProvider expectedOriginProvider) - { - var origin = mc.Origin; - Debug.Assert (origin != null); - if (GetActualOriginDisplayName (origin?.MemberDefinition) == ConvertSignatureToIlcFormat (GetExpectedOriginDisplayName (expectedOriginProvider))) - return true; - - var actualMember = origin!.Value.MemberDefinition; - // Compensate for cases where for some reason the OM doesn't preserve the declaring types - // on certain things after trimming. - if (actualMember != null && GetOwningType (actualMember) == null && - GetMemberName (actualMember) == (expectedOriginProvider as IMemberDefinition)?.Name) - return true; - - return false; - } - - static TypeDesc? GetOwningType (TypeSystemEntity entity) => entity switch { - DefType defType => defType.ContainingType, - MethodDesc method => method.OwningType, - FieldDesc field => field.OwningType, - _ => null - }; - - static string? GetMemberName (TypeSystemEntity? entity) => entity switch { - DefType defType => defType.Name, - MethodDesc method => method.Name, - FieldDesc field => field.Name, - _ => null - }; - - static string? GetActualOriginDisplayName (TypeSystemEntity? entity) => entity switch { - DefType defType => TrimAssemblyNamePrefix (defType.ToString ()), - MethodDesc method => TrimAssemblyNamePrefix (method.GetDisplayName ()), - FieldDesc field => TrimAssemblyNamePrefix (field.ToString ()), - ModuleDesc module => module.Assembly.GetName ().Name, - _ => null - }; - - static string TrimAssemblyNamePrefix (string name) - { - if (name.StartsWith ('[')) { - int i = name.IndexOf (']'); - if (i > 0) { - return name.Substring (i + 1); - } - } - - return name; - } - - static string GetExpectedOriginDisplayName (ICustomAttributeProvider provider) => - provider switch { - MethodDefinition method => method.GetDisplayName (), - FieldDefinition field => field.GetDisplayName (), - IMemberDefinition member => member.FullName, - AssemblyDefinition asm => asm.Name.Name, - _ => throw new NotImplementedException () - }; - - static bool MessageTextContains (string message, string value) - { - // This is a workaround for different formatting of methods between ilc and linker/analyzer - // Sometimes they're written with a space after comma and sometimes without - // Method(String,String) - ilc - // Method(String, String) - linker/analyzer - return message.Contains (value) || message.Contains (ConvertSignatureToIlcFormat (value)); - } - - static string ConvertSignatureToIlcFormat (string value) - { - if (value.Contains ('(') || value.Contains ('<')) { - value = value.Replace (", ", ","); - } - - return value; - } - } - - static bool HasAttribute (ICustomAttributeProvider caProvider, string attributeName) - { - if (caProvider is AssemblyDefinition assembly && assembly.EntryPoint != null) - return assembly.EntryPoint.DeclaringType.CustomAttributes - .Any (attr => attr.AttributeType.Name == attributeName); - - if (caProvider is TypeDefinition type) - return type.CustomAttributes.Any (attr => attr.AttributeType.Name == attributeName); - - return false; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs deleted file mode 100644 index 37883af7d3bda..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SetupCompileInfo.cs +++ /dev/null @@ -1,23 +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 Mono.Linker.Tests.Extensions; - -#nullable disable - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class SetupCompileInfo - { - public string OutputName; - public NPath[] SourceFiles; - public string[] Defines; - public string[] References; - public SourceAndDestinationPair[] Resources; - public string AdditionalArguments; - public string CompilerToUse; - public bool AddAsReference; - public bool RemoveFromLinkerInput; - public string OutputSubFolder; - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs deleted file mode 100644 index 52d333d9caf6a..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/SourceAndDestinationPair.cs +++ /dev/null @@ -1,15 +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 Mono.Linker.Tests.Extensions; - -#nullable disable - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class SourceAndDestinationPair - { - public NPath Source; - public string DestinationFileName; - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs deleted file mode 100644 index dec3270905e44..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseAssemblyResolver.cs +++ /dev/null @@ -1,43 +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 Mono.Cecil; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestCaseAssemblyResolver : DefaultAssemblyResolver - { - readonly HashSet itemsToDispose; - - public TestCaseAssemblyResolver () - { - itemsToDispose = new HashSet (); - } - - public override AssemblyDefinition? Resolve (AssemblyNameReference name, ReaderParameters parameters) - { - var assembly = base.Resolve (name, parameters); - - if (assembly == null) - return null; - - // Don't do any caching because the reader parameters could be different each time - // but we still want to track items that need to be disposed for easy clean up - itemsToDispose.Add (assembly); - - if (assembly.MainModule.SymbolReader != null) - itemsToDispose.Add (assembly.MainModule.SymbolReader); - return assembly; - } - - protected override void Dispose (bool disposing) - { - foreach (var item in itemsToDispose) - item.Dispose (); - - base.Dispose (disposing); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs deleted file mode 100644 index 1f9fe04d70e11..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCollector.cs +++ /dev/null @@ -1,165 +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.Linq; -using Mono.Cecil; -using Mono.Linker.Tests.Cases.Expectations.Metadata; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCases; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestCaseCollector - { - private readonly NPath _rootDirectory; - private readonly NPath _testCaseAssemblyPath; - - public TestCaseCollector (string rootDirectory, string testCaseAssemblyPath) - : this (rootDirectory.ToNPath (), testCaseAssemblyPath.ToNPath ()) - { - } - - public TestCaseCollector (NPath rootDirectory, NPath testCaseAssemblyPath) - { - _rootDirectory = rootDirectory; - _testCaseAssemblyPath = testCaseAssemblyPath; - } - - public IEnumerable Collect () - { - return Collect (AllSourceFiles ()); - } - - public TestCase? Collect (NPath sourceFile) - { - return Collect (new[] { sourceFile }).FirstOrDefault (); - } - - public IEnumerable Collect (IEnumerable sourceFiles) - { - _rootDirectory.DirectoryMustExist (); - _testCaseAssemblyPath.FileMustExist (); - - using (var caseAssemblyDefinition = AssemblyDefinition.ReadAssembly (_testCaseAssemblyPath.ToString ())) { - foreach (var file in sourceFiles) { - if (CreateCase (caseAssemblyDefinition, file, out TestCase? testCase) && testCase != null) - yield return testCase; - } - } - } - - public IEnumerable AllSourceFiles () - { - _rootDirectory.DirectoryMustExist (); - - foreach (var file in _rootDirectory.Files ("*.cs")) { - yield return file; - } - - foreach (var subDir in _rootDirectory.Directories ()) { - if (subDir.FileName == "bin" || subDir.FileName == "obj" || subDir.FileName == "Properties") - continue; - - foreach (var file in subDir.Files ("*.cs", true)) { - - var relativeParents = file.RelativeTo (_rootDirectory); - // Magic : Anything in a directory named Dependencies is assumed to be a dependency to a test case - // and never a test itself - // This makes life a little easier when writing these supporting files as it removes some constraints you would previously have - // had to follow such as ensuring a class exists that matches the file name and putting [NotATestCase] on that class - if (relativeParents.RecursiveParents.Any (p => p.Elements.Any () && p.FileName == "Dependencies")) - continue; - - // Magic: Anything in a directory named Individual is expected to be ran by it's own [Test] rather than as part of [TestCaseSource] - if (relativeParents.RecursiveParents.Any (p => p.Elements.Any () && p.FileName == "Individual")) - continue; - - yield return file; - } - } - } - - public TestCase? CreateIndividualCase (Type testCaseType) - { - _rootDirectory.DirectoryMustExist (); - _testCaseAssemblyPath.FileMustExist (); - - var pathRelativeToAssembly = $"{testCaseType.FullName?.Substring (testCaseType.Module.Name.Length - 3).Replace ('.', '/')}.cs"; - var fullSourcePath = _rootDirectory.Combine (pathRelativeToAssembly).FileMustExist (); - - using (var caseAssemblyDefinition = AssemblyDefinition.ReadAssembly (_testCaseAssemblyPath.ToString ())) { - if (!CreateCase (caseAssemblyDefinition, fullSourcePath, out TestCase? testCase)) - throw new ArgumentException ($"Could not create a test case for `{testCaseType}`. Ensure the namespace matches it's location on disk"); - - return testCase; - } - } - - private bool CreateCase (AssemblyDefinition caseAssemblyDefinition, NPath sourceFile, out TestCase? testCase) - { - var potentialCase = new TestCase (sourceFile, _rootDirectory, _testCaseAssemblyPath); - - var typeDefinition = FindTypeDefinition (caseAssemblyDefinition, potentialCase); - - testCase = null; - - if (typeDefinition == null) { - Console.WriteLine ($"Could not find the matching type for test case {sourceFile}. Ensure the file name and class name match"); - return false; - } - - if (typeDefinition.HasAttribute (nameof (NotATestCaseAttribute))) { - return false; - } - - // Verify the class as a static main method - var mainMethod = typeDefinition.Methods.FirstOrDefault (m => m.Name == "Main"); - - if (mainMethod == null) { - Console.WriteLine ($"{typeDefinition} in {sourceFile} is missing a Main() method"); - return false; - } - - if (!mainMethod.IsStatic) { - Console.WriteLine ($"The Main() method for {typeDefinition} in {sourceFile} should be static"); - return false; - } - - testCase = potentialCase; - return true; - } - - private static TypeDefinition? FindTypeDefinition (AssemblyDefinition caseAssemblyDefinition, TestCase testCase) - { - var typeDefinition = caseAssemblyDefinition.MainModule.GetType (testCase.ReconstructedFullTypeName); - - // For all of the Test Cases, the full type name we constructed from the directory structure will be correct and we can successfully find - // the type from GetType. - if (typeDefinition != null) - return typeDefinition; - - // However, some of types are supporting types rather than test cases. and may not follow the standardized naming scheme of the test cases - // We still need to be able to locate these type defs so that we can parse some of the metadata on them. - // One example, Unity run's into this with it's tests that require a type UnityEngine.MonoBehaviours to exist. This tpe is defined in it's own - // file and it cannot follow our standardized naming directory & namespace naming scheme since the namespace must be UnityEngine - foreach (var type in caseAssemblyDefinition.MainModule.Types) { - // Let's assume we should never have to search for a test case that has no namespace. If we don't find the type from GetType, then o well, that's not a test case. - if (string.IsNullOrEmpty (type.Namespace)) - continue; - - if (type.Name == testCase.Name) { - // This isn't foolproof, but let's do a little extra vetting to make sure the type we found corresponds to the source file we are - // processing. - if (!testCase.SourceFile.ReadAllText ().Contains ($"namespace {type.Namespace}")) - continue; - - return type; - } - } - - return null; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs deleted file mode 100644 index 1aa354f58176b..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompilationMetadataProvider.cs +++ /dev/null @@ -1,242 +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.CodeAnalysis; -using System.IO; -using System.Linq; -using Mono.Cecil; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Metadata; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCases; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestCaseCompilationMetadataProvider : BaseMetadataProvider - { - - public TestCaseCompilationMetadataProvider (TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition) - : base (testCase, fullTestCaseAssemblyDefinition) - { - - } - - public virtual TestRunCharacteristics Characteristics => - TestRunCharacteristics.TargetingNetCore | TestRunCharacteristics.SupportsDefaultInterfaceMethods | TestRunCharacteristics.SupportsStaticInterfaceMethods; - - public virtual bool IsIgnored ([NotNullWhen(true)] out string? reason) - { - var ignoreAttribute = _testCaseTypeDefinition.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == nameof (IgnoreTestCaseAttribute)); - if (ignoreAttribute != null) { - if (ignoreAttribute.ConstructorArguments.Count == 1) { - reason = (string) ignoreAttribute.ConstructorArguments.First ().Value; - return true; - } else { - throw new ArgumentException ($"Unhandled {nameof (IgnoreTestCaseAttribute)} constructor with {ignoreAttribute.ConstructorArguments} arguments"); - } - } - - var requirementsAttribute = _testCaseTypeDefinition.CustomAttributes.FirstOrDefault (attr => attr.AttributeType.Name == nameof (TestCaseRequirementsAttribute)); - if (requirementsAttribute != null) { - if (requirementsAttribute.ConstructorArguments.Count == 2) { - var testCaseRequirements = (TestRunCharacteristics) requirementsAttribute.ConstructorArguments[0].Value; - - foreach (var value in Enum.GetValues (typeof (TestRunCharacteristics))) { - if (IsRequirementMissing ((TestRunCharacteristics) value, testCaseRequirements)) { - reason = (string) requirementsAttribute.ConstructorArguments[1].Value; - return true; - } - } - } else { - throw new ArgumentException ($"Unhandled {nameof (TestCaseRequirementsAttribute)} constructor with {requirementsAttribute.ConstructorArguments} arguments"); - } - } - - reason = null; - return false; - } - - bool IsRequirementMissing (TestRunCharacteristics requirement, TestRunCharacteristics testCaseRequirements) - { - return testCaseRequirements.HasFlag (requirement) && !Characteristics.HasFlag (requirement); - } - - public virtual IEnumerable GetDefines () - { - // There are a few tests related to native pdbs where the assertions are different between windows and non-windows - // To enable test cases to define different expected behavior we set this special define - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - yield return "WIN32"; - - if (Characteristics.HasFlag (TestRunCharacteristics.TargetingNetCore)) - yield return "NETCOREAPP"; - - if (Characteristics.HasFlag (TestRunCharacteristics.SupportsDefaultInterfaceMethods)) - yield return "SUPPORTS_DEFAULT_INTERFACE_METHODS"; - - foreach (var attr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (DefineAttribute))) - yield return (string) attr.ConstructorArguments.First ().Value; - } - - public virtual string GetAssemblyName () - { - var asLibraryAttribute = _testCaseTypeDefinition.CustomAttributes - .FirstOrDefault (attr => attr.AttributeType.Name == nameof (SetupCompileAsLibraryAttribute)); - var defaultName = asLibraryAttribute == null ? "test.exe" : "test.dll"; - return GetOptionAttributeValue (nameof (SetupCompileAssemblyNameAttribute), defaultName)!; - } - - public virtual string GetCSharpCompilerToUse () - { - return GetOptionAttributeValue (nameof (SetupCSharpCompilerToUseAttribute), string.Empty)!.ToLower (); - } - - public virtual IEnumerable GetSetupCompilerArguments () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupCompileArgumentAttribute)) - .Select (attr => (string) attr.ConstructorArguments.First ().Value); - } - - public virtual IEnumerable AdditionalFilesToSandbox () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SandboxDependencyAttribute)) - .Select (GetSourceAndRelativeDestinationValue); - } - - static string GetReferenceDir () - { - string runtimeDir = Path.GetDirectoryName (typeof (object).Assembly.Location)!; - string ncaVersion = Path.GetFileName (runtimeDir); - string dotnetDir = Path.GetDirectoryName (Path.GetDirectoryName (Path.GetDirectoryName (runtimeDir)))!; - return Path.Combine (dotnetDir, "packs", "Microsoft.NETCore.App.Ref", ncaVersion, "ref", PathUtilities.TFMDirectoryName); - } - - public virtual IEnumerable GetCommonReferencedAssemblies (NPath workingDirectory) - { - yield return workingDirectory.Combine ("Mono.Linker.Tests.Cases.Expectations.dll").ToString (); - if (Characteristics.HasFlag (TestRunCharacteristics.TargetingNetCore)) { - string referenceDir = GetReferenceDir (); - - yield return Path.Combine (referenceDir, "mscorlib.dll"); - yield return Path.Combine (referenceDir, "System.Collections.dll"); - yield return Path.Combine (referenceDir, "System.ComponentModel.TypeConverter.dll"); - yield return Path.Combine (referenceDir, "System.Console.dll"); - yield return Path.Combine (referenceDir, "System.Linq.Expressions.dll"); - yield return Path.Combine (referenceDir, "System.ObjectModel.dll"); - yield return Path.Combine (referenceDir, "System.Runtime.dll"); - yield return Path.Combine (referenceDir, "System.Runtime.Extensions.dll"); - yield return Path.Combine (referenceDir, "System.Runtime.InteropServices.dll"); - } else { - yield return "mscorlib.dll"; - } - } - - public virtual IEnumerable GetReferencedAssemblies (NPath workingDirectory) - { - foreach (var fileName in GetReferenceValues ()) { - - if (fileName.StartsWith ("System.", StringComparison.Ordinal) || fileName.StartsWith ("Mono.", StringComparison.Ordinal) || fileName.StartsWith ("Microsoft.", StringComparison.Ordinal)) { - if (Characteristics.HasFlag (TestRunCharacteristics.TargetingNetCore)) { - var referenceDir = GetReferenceDir (); - var filePath = Path.Combine (referenceDir, fileName); - - if (File.Exists (filePath)) { - yield return filePath; - } else { - yield return fileName; - } - } else { - yield return fileName; - } - } else { - // Drop any relative path information. Sandboxing will have taken care of copying the reference to the directory - yield return workingDirectory.Combine (Path.GetFileName (fileName)); - } - } - } - - public virtual IEnumerable GetReferenceDependencies () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (ReferenceDependencyAttribute)) - .Select (attr => (string) attr.ConstructorArguments[0].Value); - } - - public virtual IEnumerable GetReferenceValues () - { - foreach (var referenceAttr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (ReferenceAttribute))) - yield return (string) referenceAttr.ConstructorArguments.First ().Value; - } - - public virtual IEnumerable GetResources () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupCompileResourceAttribute)) - .Select (GetSourceAndRelativeDestinationValue); - } - - public virtual IEnumerable GetSetupCompileAssembliesBefore () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupCompileBeforeAttribute)) - .Select (CreateSetupCompileAssemblyInfo); - } - - public virtual IEnumerable GetSetupCompileAssembliesAfter () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupCompileAfterAttribute)) - .Select (CreateSetupCompileAssemblyInfo); - } - - private SetupCompileInfo CreateSetupCompileAssemblyInfo (CustomAttribute attribute) - { - var ctorArguments = attribute.ConstructorArguments; - return new SetupCompileInfo { - OutputName = (string) ctorArguments[0].Value, - SourceFiles = SourceFilesForAttributeArgument (ctorArguments[1]), - References = ((CustomAttributeArgument[]) ctorArguments[2].Value)?.Select (arg => arg.Value.ToString ()).ToArray (), - Defines = ((CustomAttributeArgument[]) ctorArguments[3].Value)?.Select (arg => arg.Value.ToString ()).ToArray (), - Resources = ResourcesForAttributeArgument (ctorArguments[4]), - AdditionalArguments = (string) ctorArguments[5].Value, - CompilerToUse = (string) ctorArguments[6].Value, - AddAsReference = ctorArguments.Count >= 8 ? (bool) ctorArguments[7].Value : true, - RemoveFromLinkerInput = ctorArguments.Count >= 9 ? (bool) ctorArguments[8].Value : false, - OutputSubFolder = ctorArguments.Count >= 10 ? (string) ctorArguments[9].Value : null - }; - } - - protected NPath[] SourceFilesForAttributeArgument (CustomAttributeArgument attributeArgument) - { - return ((CustomAttributeArgument[]) attributeArgument.Value) - .Select (attributeArg => SourceFileForAttributeArgumentValue (attributeArg.Value)) - .Distinct () - .ToArray (); - } - - protected SourceAndDestinationPair[]? ResourcesForAttributeArgument (CustomAttributeArgument attributeArgument) - { - return ((CustomAttributeArgument[]) attributeArgument.Value) - ?.Select (arg => { - var referenceArg = (CustomAttributeArgument) arg.Value; - if (referenceArg.Value is string source) { - var fullSource = MakeSourceTreeFilePathAbsolute (source); - return new SourceAndDestinationPair { - Source = fullSource, - DestinationFileName = fullSource.FileName - }; - } - var sourceAndDestination = (CustomAttributeArgument[]) referenceArg.Value; - return new SourceAndDestinationPair { - Source = MakeSourceTreeFilePathAbsolute (sourceAndDestination[0].Value!.ToString ()!), - DestinationFileName = sourceAndDestination[1].Value!.ToString ()! - }; - }) - ?.ToArray (); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs deleted file mode 100644 index 3f47904efa69e..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseCompiler.cs +++ /dev/null @@ -1,411 +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.IO; -using System.Linq; -using System.Text; -using Mono.Linker.Tests.Extensions; -using Xunit; -#if NETCOREAPP -using System.Runtime.InteropServices; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Emit; -using Microsoft.CodeAnalysis.CSharp; -#endif - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestCaseCompiler - { - protected readonly TestCaseCompilationMetadataProvider _metadataProvider; - protected readonly TestCaseSandbox _sandbox; - protected readonly ILInputCompiler _ilCompiler; - - public TestCaseCompiler (TestCaseSandbox sandbox, TestCaseCompilationMetadataProvider metadataProvider) - : this (sandbox, metadataProvider, new ILInputCompiler ()) - { - } - - public TestCaseCompiler (TestCaseSandbox sandbox, TestCaseCompilationMetadataProvider metadataProvider, ILInputCompiler ilCompiler) - { - _ilCompiler = ilCompiler; - _sandbox = sandbox; - _metadataProvider = metadataProvider; - } - - public NPath CompileTestIn (NPath outputDirectory, string outputName, IEnumerable sourceFiles, string[] commonReferences, string[] mainAssemblyReferences, IEnumerable? defines, NPath[] resources, string[] additionalArguments) - { - var originalCommonReferences = commonReferences.Select (r => r.ToNPath ()).ToArray (); - var originalDefines = defines?.ToArray () ?? new string[0]; - - Prepare (outputDirectory); - - var removeFromLinkerInputAssemblies = new List (); - var compiledReferences = CompileBeforeTestCaseAssemblies (outputDirectory, originalCommonReferences, originalDefines, removeFromLinkerInputAssemblies).ToArray (); - var allTestCaseReferences = originalCommonReferences - .Concat (compiledReferences) - .Concat (mainAssemblyReferences.Select (r => r.ToNPath ())) - .ToArray (); - - var options = CreateOptionsForTestCase ( - outputDirectory.Combine (outputName), - sourceFiles.Select (s => s.ToNPath ()).ToArray (), - allTestCaseReferences, - originalDefines, - resources, - additionalArguments); - var testAssembly = CompileAssembly (options); - - - // The compile after step is used by tests to mess around with the input to the linker. Generally speaking, it doesn't seem like we would ever want to mess with the - // expectations assemblies because this would undermine our ability to inspect them for expected results during ResultChecking. The UnityLinker UnresolvedHandling tests depend on this - // behavior of skipping the after test compile - if (outputDirectory != _sandbox.ExpectationsDirectory) { - CompileAfterTestCaseAssemblies (outputDirectory, originalCommonReferences, originalDefines, removeFromLinkerInputAssemblies); - - foreach (var assemblyToRemove in removeFromLinkerInputAssemblies) - assemblyToRemove.DeleteIfExists (); - } - - return testAssembly; - } - - protected virtual void Prepare (NPath outputDirectory) - { - } - - protected virtual CompilerOptions CreateOptionsForTestCase (NPath outputPath, NPath[] sourceFiles, NPath[] references, string[] defines, NPath[] resources, string[] additionalArguments) - { - return new CompilerOptions { - OutputPath = outputPath, - SourceFiles = sourceFiles, - References = references, - Defines = defines.Concat (_metadataProvider.GetDefines ()).ToArray (), - Resources = resources, - AdditionalArguments = additionalArguments, - CompilerToUse = _metadataProvider.GetCSharpCompilerToUse () - }; - } - - protected virtual CompilerOptions CreateOptionsForSupportingAssembly (SetupCompileInfo setupCompileInfo, NPath outputDirectory, NPath[] sourceFiles, NPath[] references, string[] defines, NPath[] resources) - { - var allDefines = defines.Concat (setupCompileInfo.Defines ?? new string[0]).ToArray (); - var allReferences = references.Concat (setupCompileInfo.References?.Select (p => MakeSupportingAssemblyReferencePathAbsolute (outputDirectory, p)) ?? new NPath[0]).ToArray (); - string[]? additionalArguments = string.IsNullOrEmpty (setupCompileInfo.AdditionalArguments) ? null : new[] { setupCompileInfo.AdditionalArguments }; - return new CompilerOptions { - OutputPath = outputDirectory.Combine (setupCompileInfo.OutputName), - SourceFiles = sourceFiles, - References = allReferences, - Defines = allDefines, - Resources = resources, - AdditionalArguments = additionalArguments, - CompilerToUse = setupCompileInfo.CompilerToUse?.ToLower () - }; - } - - private IEnumerable CompileBeforeTestCaseAssemblies (NPath outputDirectory, NPath[] references, string[] defines, IList removeFromLinkerInputAssemblies) - { - foreach (var setupCompileInfo in _metadataProvider.GetSetupCompileAssembliesBefore ()) { - NPath outputFolder; - if (setupCompileInfo.OutputSubFolder == null) { - outputFolder = outputDirectory; - } else { - outputFolder = outputDirectory.Combine (setupCompileInfo.OutputSubFolder); - Directory.CreateDirectory (outputFolder.ToString ()); - } - - var options = CreateOptionsForSupportingAssembly ( - setupCompileInfo, - outputFolder, - CollectSetupBeforeSourcesFiles (setupCompileInfo), - references, - defines, - CollectSetupBeforeResourcesFiles (setupCompileInfo)); - var output = CompileAssembly (options); - - if (setupCompileInfo.RemoveFromLinkerInput) - removeFromLinkerInputAssemblies.Add (output); - - if (setupCompileInfo.AddAsReference) - yield return output; - } - } - - private void CompileAfterTestCaseAssemblies (NPath outputDirectory, NPath[] references, string[] defines, IList removeFromLinkerInputAssemblies) - { - foreach (var setupCompileInfo in _metadataProvider.GetSetupCompileAssembliesAfter ()) { - var options = CreateOptionsForSupportingAssembly ( - setupCompileInfo, - outputDirectory, - CollectSetupAfterSourcesFiles (setupCompileInfo), - references, - defines, - CollectSetupAfterResourcesFiles (setupCompileInfo)); - var output = CompileAssembly (options); - - if (setupCompileInfo.RemoveFromLinkerInput) - removeFromLinkerInputAssemblies.Add (output); - } - } - - private NPath[] CollectSetupBeforeSourcesFiles (SetupCompileInfo info) - { - return CollectSourceFilesFrom (_sandbox.BeforeReferenceSourceDirectoryFor (info.OutputName)); - } - - private NPath[] CollectSetupAfterSourcesFiles (SetupCompileInfo info) - { - return CollectSourceFilesFrom (_sandbox.AfterReferenceSourceDirectoryFor (info.OutputName)); - } - - private NPath[] CollectSetupBeforeResourcesFiles (SetupCompileInfo info) - { - return _sandbox.BeforeReferenceResourceDirectoryFor (info.OutputName).Files ().ToArray (); - } - - private NPath[] CollectSetupAfterResourcesFiles (SetupCompileInfo info) - { - return _sandbox.AfterReferenceResourceDirectoryFor (info.OutputName).Files ().ToArray (); - } - - private static NPath[] CollectSourceFilesFrom (NPath directory) - { - var sourceFiles = directory.Files ("*.cs").ToArray (); - if (sourceFiles.Length > 0) - return sourceFiles; - - sourceFiles = directory.Files ("*.il").ToArray (); - if (sourceFiles.Length > 0) - return sourceFiles; - - throw new FileNotFoundException ($"Didn't find any sources files in {directory}"); - } - - protected static NPath MakeSupportingAssemblyReferencePathAbsolute (NPath outputDirectory, string referenceFileName) - { - // Not a good idea to use a full path in a test, but maybe someone is trying to quickly test something locally - if (Path.IsPathRooted (referenceFileName)) - return referenceFileName.ToNPath (); - -#if NETCOREAPP - if (referenceFileName.StartsWith ("System.", StringComparison.Ordinal) || - referenceFileName.StartsWith ("Mono.", StringComparison.Ordinal) || - referenceFileName.StartsWith ("Microsoft.", StringComparison.Ordinal) || - referenceFileName == "netstandard.dll") { - - var frameworkDir = Path.GetFullPath (Path.GetDirectoryName (typeof (object).Assembly.Location)!); - var filePath = Path.Combine (frameworkDir, referenceFileName); - - if (File.Exists (filePath)) - return filePath.ToNPath (); - } -#endif - - var possiblePath = outputDirectory.Combine (referenceFileName); - if (possiblePath.FileExists ()) - return possiblePath; - - return referenceFileName.ToNPath (); - } - - protected NPath CompileAssembly (CompilerOptions options) - { - if (options.SourceFiles.Any (path => path.ExtensionWithDot == ".cs")) - return CompileCSharpAssembly (options); - - if (options.SourceFiles.Any (path => path.ExtensionWithDot == ".il")) - return CompileIlAssembly (options); - - throw new NotSupportedException ($"Unable to compile sources files with extension `{options.SourceFiles.First ().ExtensionWithDot}`"); - } - - protected virtual NPath CompileCSharpAssemblyWithDefaultCompiler (CompilerOptions options) - { -#if NETCOREAPP - return CompileCSharpAssemblyWithRoslyn (options); -#else - return CompileCSharpAssemblyWithCsc (options); -#endif - } - -#if NETCOREAPP - protected virtual NPath CompileCSharpAssemblyWithRoslyn (CompilerOptions options) - { - var languageVersion = LanguageVersion.Default; - var compilationOptions = new CSharpCompilationOptions ( - outputKind: options.OutputPath.FileName.EndsWith (".exe") ? OutputKind.ConsoleApplication : OutputKind.DynamicallyLinkedLibrary, - assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default - ); - // Default debug info format for the current platform. - DebugInformationFormat debugType = RuntimeInformation.IsOSPlatform (OSPlatform.Windows) ? DebugInformationFormat.Pdb : DebugInformationFormat.PortablePdb; - bool emitPdb = false; - if (options.AdditionalArguments != null) { - foreach (var option in options.AdditionalArguments) { - switch (option) { - case "/unsafe": - compilationOptions = compilationOptions.WithAllowUnsafe (true); - break; - case "/optimize+": - compilationOptions = compilationOptions.WithOptimizationLevel (OptimizationLevel.Release); - break; - case "/debug:full": - case "/debug:pdbonly": - // Use platform's default debug info. This behavior is the same as csc. - emitPdb = true; - break; - case "/debug:portable": - emitPdb = true; - debugType = DebugInformationFormat.PortablePdb; - break; - case "/debug:embedded": - emitPdb = true; - debugType = DebugInformationFormat.Embedded; - break; - case "/langversion:7.3": - languageVersion = LanguageVersion.CSharp7_3; - break; - - } - } - } - var parseOptions = new CSharpParseOptions (preprocessorSymbols: options.Defines, languageVersion: languageVersion); - var emitOptions = new EmitOptions (debugInformationFormat: debugType); - var pdbPath = (!emitPdb || debugType == DebugInformationFormat.Embedded) ? null : options.OutputPath.ChangeExtension (".pdb").ToString (); - - var syntaxTrees = options.SourceFiles.Select (p => - CSharpSyntaxTree.ParseText ( - text: p.ReadAllText (), - options: parseOptions - ) - ); - - var compilation = CSharpCompilation.Create ( - assemblyName: options.OutputPath.FileNameWithoutExtension, - syntaxTrees: syntaxTrees, - references: options.References.Select (r => MetadataReference.CreateFromFile (r)), - options: compilationOptions - ); - - var manifestResources = options.Resources.Select (r => { - var fullPath = r.ToString (); - return new ResourceDescription ( - resourceName: Path.GetFileName (fullPath), - dataProvider: () => new FileStream (fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), - isPublic: true - ); - }); - - EmitResult result; - using (var outputStream = File.Create (options.OutputPath.ToString ())) - using (var pdbStream = pdbPath == null ? null : File.Create (pdbPath)) { - result = compilation.Emit ( - peStream: outputStream, - pdbStream: pdbStream, - manifestResources: manifestResources, - options: emitOptions - ); - } - - var errors = new StringBuilder (); - if (result.Success) - return options.OutputPath; - - foreach (var diagnostic in result.Diagnostics) - errors.AppendLine (diagnostic.ToString ()); - throw new Exception ("Roslyn compilation errors: " + errors); - } -#endif - - protected virtual NPath CompileCSharpAssemblyWithCsc (CompilerOptions options) - { -#if NETCOREAPP - return CompileCSharpAssemblyWithRoslyn (options); -#else - return CompileCSharpAssemblyWithExternalCompiler (LocateCscExecutable (), options, "/shared "); -#endif - } - - protected virtual NPath CompileCSharpAssemblyWithMcs (CompilerOptions options) - { - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - CompileCSharpAssemblyWithExternalCompiler (LocateMcsExecutable (), options, string.Empty); - - return CompileCSharpAssemblyWithDefaultCompiler (options); - } - - protected NPath CompileCSharpAssemblyWithExternalCompiler (string executable, CompilerOptions options, string compilerSpecificArguments) - { - var capturedOutput = new List (); - var process = new Process (); - process.StartInfo.FileName = executable; - process.StartInfo.Arguments = OptionsToCompilerCommandLineArguments (options, compilerSpecificArguments); - process.StartInfo.UseShellExecute = false; - process.StartInfo.CreateNoWindow = true; - process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; - process.StartInfo.RedirectStandardOutput = true; - process.OutputDataReceived += (sender, args) => capturedOutput.Add (args.Data!); - process.Start (); - process.BeginOutputReadLine (); - process.WaitForExit (); - - if (process.ExitCode != 0) - Assert.True (false, $"Failed to compile assembly with csc: {options.OutputPath}\n{capturedOutput.Aggregate ((buff, s) => buff + Environment.NewLine + s)}"); - - return options.OutputPath; - } - - static string LocateMcsExecutable () - { - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - throw new IgnoreTestException ("We don't have a universal way of locating mcs on Windows"); - - return "mcs"; - } - - protected string OptionsToCompilerCommandLineArguments (CompilerOptions options, string compilerSpecificArguments) - { - var builder = new StringBuilder (); - if (!string.IsNullOrEmpty (compilerSpecificArguments)) - builder.Append (compilerSpecificArguments); - builder.Append ($"/out:{options.OutputPath}"); - var target = options.OutputPath.ExtensionWithDot == ".exe" ? "exe" : "library"; - builder.Append ($" /target:{target}"); - if (options.Defines != null && options.Defines.Length > 0) - builder.Append (options.Defines.Aggregate (string.Empty, (buff, arg) => $"{buff} /define:{arg}")); - - builder.Append (options.References.Aggregate (string.Empty, (buff, arg) => $"{buff} /r:{arg}")); - - if (options.Resources != null && options.Resources.Length > 0) - builder.Append (options.Resources.Aggregate (string.Empty, (buff, arg) => $"{buff} /res:{arg}")); - - if (options.AdditionalArguments != null && options.AdditionalArguments.Length > 0) - builder.Append (options.AdditionalArguments.Aggregate (string.Empty, (buff, arg) => $"{buff} {arg}")); - - builder.Append (options.SourceFiles.Aggregate (string.Empty, (buff, arg) => $"{buff} {arg}")); - - return builder.ToString (); - } - - protected NPath CompileCSharpAssembly (CompilerOptions options) - { - if (string.IsNullOrEmpty (options.CompilerToUse)) - return CompileCSharpAssemblyWithDefaultCompiler (options); - - if (options.CompilerToUse == "csc") - return CompileCSharpAssemblyWithCsc (options); - - if (options.CompilerToUse == "mcs") - return CompileCSharpAssemblyWithMcs (options); - - throw new ArgumentException ($"Invalid compiler value `{options.CompilerToUse}`"); - } - - protected NPath CompileIlAssembly (CompilerOptions options) - { - return _ilCompiler.Compile (options); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs deleted file mode 100644 index 161e9af1c33ce..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseLinkerOptions.cs +++ /dev/null @@ -1,36 +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.Collections.Generic; - -#nullable disable - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestCaseLinkerOptions - { - public string TrimMode; - public string DefaultAssembliesAction; - public List<(string Action, string Assembly)> AssembliesAction = new(); - - public string Il8n; - public bool IgnoreDescriptors; - public bool IgnoreSubstitutions; - public bool IgnoreLinkAttributes; - public string KeepTypeForwarderOnlyAssemblies; - public string KeepDebugMembers; - public string LinkSymbols; - public bool SkipUnresolved; - public bool StripDescriptors; - public bool StripSubstitutions; - public bool StripLinkAttributes; - - public List> AdditionalArguments = new List> (); - - public List Descriptors = new List (); - - public List Substitutions = new List (); - - public List LinkAttributes = new List (); - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs deleted file mode 100644 index cf3a762396379..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseMetadataProvider.cs +++ /dev/null @@ -1,141 +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.IO; -using System.Linq; -using Mono.Cecil; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Cases.Expectations.Metadata; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCases; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestCaseMetadataProvider : BaseMetadataProvider - { - public TestCaseMetadataProvider (TestCase testCase, AssemblyDefinition fullTestCaseAssemblyDefinition) - : base (testCase, fullTestCaseAssemblyDefinition) - { - } - - public virtual TestCaseLinkerOptions GetLinkerOptions (NPath inputPath) - { - var tclo = new TestCaseLinkerOptions { - Il8n = GetOptionAttributeValue (nameof (Il8nAttribute), "none"), - IgnoreDescriptors = GetOptionAttributeValue (nameof (IgnoreDescriptorsAttribute), true), - IgnoreSubstitutions = GetOptionAttributeValue (nameof (IgnoreSubstitutionsAttribute), true), - IgnoreLinkAttributes = GetOptionAttributeValue (nameof (IgnoreLinkAttributesAttribute), true), - KeepTypeForwarderOnlyAssemblies = GetOptionAttributeValue (nameof (KeepTypeForwarderOnlyAssembliesAttribute), string.Empty), - KeepDebugMembers = GetOptionAttributeValue (nameof (SetupLinkerKeepDebugMembersAttribute), string.Empty), - LinkSymbols = GetOptionAttributeValue (nameof (SetupLinkerLinkSymbolsAttribute), string.Empty), - TrimMode = GetOptionAttributeValue (nameof (SetupLinkerTrimModeAttribute), null), - DefaultAssembliesAction = GetOptionAttributeValue (nameof (SetupLinkerDefaultActionAttribute), null), - SkipUnresolved = GetOptionAttributeValue (nameof (SkipUnresolvedAttribute), false), - StripDescriptors = GetOptionAttributeValue (nameof (StripDescriptorsAttribute), true), - StripSubstitutions = GetOptionAttributeValue (nameof (StripSubstitutionsAttribute), true), - StripLinkAttributes = GetOptionAttributeValue (nameof (StripLinkAttributesAttribute), true), - }; - - foreach (var assemblyAction in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerActionAttribute))) { - var ca = assemblyAction.ConstructorArguments; - tclo.AssembliesAction.Add (((string) ca[0].Value, (string) ca[1].Value)); - } - - foreach (var descFile in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerDescriptorFile))) { - var ca = descFile.ConstructorArguments; - var file = (string) ca[0].Value; - tclo.Descriptors.Add (Path.Combine (inputPath, file)); - } - - foreach (var subsFile in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerSubstitutionFileAttribute))) { - var ca = subsFile.ConstructorArguments; - var file = (string) ca[0].Value; - tclo.Substitutions.Add (Path.Combine (inputPath, file)); - } - - foreach (var linkAttrFile in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkAttributesFile))) { - var ca = linkAttrFile.ConstructorArguments; - var file = (string) ca[0].Value; - tclo.LinkAttributes.Add (Path.Combine (inputPath, file)); - } - - foreach (var additionalArgumentAttr in _testCaseTypeDefinition.CustomAttributes.Where (attr => attr.AttributeType.Name == nameof (SetupLinkerArgumentAttribute))) { - var ca = additionalArgumentAttr.ConstructorArguments; - var values = ((CustomAttributeArgument[]) ca[1].Value)!.Select (arg => arg.Value.ToString ()!).ToArray (); - // Since custom attribute arguments need to be constant expressions, we need to add - // the path to the temp directory (where the custom assembly is located) here. - switch ((string) ca[0].Value) { - case "--custom-step": - int pos = values[0].IndexOf (","); - if (pos != -1) { - string custom_assembly_path = values[0].Substring (pos + 1); - if (!Path.IsPathRooted (custom_assembly_path)) - values[0] = values[0].Substring (0, pos + 1) + Path.Combine (inputPath, custom_assembly_path); - } - break; - case "-a": - if (!Path.IsPathRooted (values[0])) - values[0] = Path.Combine (inputPath, values[0]); - - break; - } - - tclo.AdditionalArguments.Add (new KeyValuePair ((string) ca[0].Value, values)); - } - - return tclo; - } - - public virtual IEnumerable GetResponseFiles () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupLinkerResponseFileAttribute)) - .Select (GetSourceAndRelativeDestinationValue); - } - - public virtual IEnumerable GetDescriptorFiles () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupLinkerDescriptorFile)) - .Select (GetSourceAndRelativeDestinationValue); - } - - public virtual IEnumerable GetSubstitutionFiles () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupLinkerSubstitutionFileAttribute)) - .Select (GetSourceAndRelativeDestinationValue); - } - - public virtual IEnumerable GetLinkAttributesFiles () - { - return _testCaseTypeDefinition.CustomAttributes - .Where (attr => attr.AttributeType.Name == nameof (SetupLinkAttributesFile)) - .Select (GetSourceAndRelativeDestinationValue); - } - - public virtual IEnumerable GetExtraLinkerReferences () - { - var netcoreappDir = Path.GetDirectoryName (typeof (object).Assembly.Location)!; - foreach (var assembly in Directory.EnumerateFiles (netcoreappDir)) { - if (Path.GetExtension (assembly) != ".dll") - continue; - var assemblyName = Path.GetFileNameWithoutExtension (assembly); - if (assemblyName.Contains ("Native")) - continue; - if (assemblyName.StartsWith ("Microsoft") || - assemblyName.StartsWith ("System") || - assemblyName == "mscorlib" || assemblyName == "netstandard") - yield return assembly.ToNPath (); - } - } - - public virtual bool LinkPublicAndFamily () - { - return _testCaseTypeDefinition.CustomAttributes - .FirstOrDefault (attr => attr.AttributeType.Name == nameof (SetupLinkerLinkPublicAndFamilyAttribute)) != null; - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs deleted file mode 100644 index c7041020c4481..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestCaseSandbox.cs +++ /dev/null @@ -1,195 +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.IO; -using Mono.Linker.Tests.Cases.Expectations.Assertions; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCases; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestCaseSandbox - { - protected readonly TestCase _testCase; - protected readonly NPath _directory; - - static readonly string _linkerAssemblyPath = "";//typeof (Trimmer).Assembly.Location; - - static NPath GetArtifactsTestPath () - { - // Converts paths like /root-folder/runtime/artifacts/bin/Mono.Linker.Tests/x64/Debug/Mono.Linker.Tests.dll - // to /root-folder/runtime/artifacts/bin/ILLink.testcases/ - string artifacts = (string) AppContext.GetData ("Mono.Linker.Tests.ArtifactsDir")!; - string tests = Path.Combine (artifacts, "ILLink.testcases"); - return new NPath (tests); - } - - public TestCaseSandbox (TestCase testCase) - : this (testCase, GetArtifactsTestPath (), Path.GetFileNameWithoutExtension (_linkerAssemblyPath)) - { - } - - public TestCaseSandbox (TestCase testCase, NPath rootTemporaryDirectory) - : this (testCase, rootTemporaryDirectory, string.Empty) - { - } - - public TestCaseSandbox (TestCase testCase, string rootTemporaryDirectory, string namePrefix) - : this (testCase, rootTemporaryDirectory.ToNPath (), namePrefix) - { - } - - public TestCaseSandbox (TestCase testCase, NPath rootTemporaryDirectory, string namePrefix) - { - _testCase = testCase; - - var rootDirectory = rootTemporaryDirectory.Combine (string.IsNullOrEmpty (namePrefix) ? "linker_tests" : namePrefix); - - var locationRelativeToRoot = testCase.SourceFile.Parent.RelativeTo (testCase.RootCasesDirectory); - var suiteDirectory = rootDirectory.Combine (locationRelativeToRoot); - _directory = suiteDirectory.Combine (testCase.SourceFile.FileNameWithoutExtension); - - _directory.DeleteContents (); - - InputDirectory = _directory.Combine ("input").EnsureDirectoryExists (); - OutputDirectory = _directory.Combine ("output").EnsureDirectoryExists (); - ExpectationsDirectory = _directory.Combine ("expectations").EnsureDirectoryExists (); - ResourcesDirectory = _directory.Combine ("resources").EnsureDirectoryExists (); - } - - public NPath InputDirectory { get; } - - public NPath OutputDirectory { get; } - - public NPath ExpectationsDirectory { get; } - - public NPath ResourcesDirectory { get; } - - public IEnumerable SourceFiles { - get { return _directory.Files ("*.cs"); } - } - - public IEnumerable ResponseFiles { - get { return InputDirectory.Files ("*.rsp"); } - } - - public IEnumerable ResourceFiles => ResourcesDirectory.Files (); - - public virtual void Populate (TestCaseCompilationMetadataProvider metadataProvider) - { - _testCase.SourceFile.Copy (_directory); - - if (_testCase.HasLinkXmlFile) - _testCase.LinkXmlFile.Copy (InputDirectory); - - CopyToInputAndExpectations (GetExpectationsAssemblyPath ()); - - foreach (var dep in metadataProvider.AdditionalFilesToSandbox ()) { - var destination = _directory.Combine (dep.DestinationFileName); - dep.Source.FileMustExist ().Copy (destination); - - // In a few niche tests we need to copy pre-built assemblies directly into the input directory. - // When this is done, we also need to copy them into the expectations directory so that if they are used - // as references we can still compile the expectations version of the assemblies - if (destination.Parent == InputDirectory) - dep.Source.Copy (ExpectationsDirectory.Combine (destination.RelativeTo (InputDirectory))); - } - - // Copy non class library dependencies to the sandbox - foreach (var fileName in metadataProvider.GetReferenceValues ()) { - if (!fileName.StartsWith ("System.", StringComparison.Ordinal) && !fileName.StartsWith ("Mono.", StringComparison.Ordinal) && !fileName.StartsWith ("Microsoft.", StringComparison.Ordinal)) - CopyToInputAndExpectations (_testCase.SourceFile.Parent.Combine (fileName.ToNPath ())); - } - - foreach (var referenceDependency in metadataProvider.GetReferenceDependencies ()) - CopyToInputAndExpectations (_testCase.SourceFile.Parent.Combine (referenceDependency.ToNPath ())); - - foreach (var res in metadataProvider.GetResources ()) { - res.Source.FileMustExist ().Copy (ResourcesDirectory.Combine (res.DestinationFileName)); - } - - foreach (var compileRefInfo in metadataProvider.GetSetupCompileAssembliesBefore ()) { - var destination = BeforeReferenceSourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists (); - compileRefInfo.SourceFiles.Copy (destination); - - destination = BeforeReferenceResourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists (); - - if (compileRefInfo.Resources == null) - continue; - - foreach (var res in compileRefInfo.Resources) - res.Source.FileMustExist ().Copy (destination.Combine (res.DestinationFileName)); - } - - foreach (var compileRefInfo in metadataProvider.GetSetupCompileAssembliesAfter ()) { - var destination = AfterReferenceSourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists (); - compileRefInfo.SourceFiles.Copy (destination); - - destination = AfterReferenceResourceDirectoryFor (compileRefInfo.OutputName).EnsureDirectoryExists (); - - if (compileRefInfo.Resources == null) - continue; - - foreach (var res in compileRefInfo.Resources) - res.Source.FileMustExist ().Copy (destination.Combine (res.DestinationFileName)); - } - } - - /// - /// Any files that are needed for linking should come from the expectations assembly so that these values - /// can be controlled using #ifs regardless of the framework the NUnit test project is compiled against - /// - /// - public virtual void PopulateFromExpectations (TestCaseMetadataProvider metadataProvider) - { - foreach (var res in metadataProvider.GetResponseFiles ()) { - res.Source.FileMustExist ().Copy (InputDirectory.Combine (res.DestinationFileName)); - } - - foreach (var res in metadataProvider.GetDescriptorFiles ()) { - res.Source.FileMustExist ().Copy (InputDirectory.Combine (res.DestinationFileName)); - } - - foreach (var res in metadataProvider.GetSubstitutionFiles ()) { - res.Source.FileMustExist ().Copy (InputDirectory.Combine (res.DestinationFileName)); - } - - foreach (var res in metadataProvider.GetLinkAttributesFiles ()) { - res.Source.FileMustExist ().Copy (InputDirectory.Combine (res.DestinationFileName)); - } - } - - private static NPath GetExpectationsAssemblyPath () - { - return new Uri (typeof (KeptAttribute).Assembly.Location).LocalPath.ToNPath (); - } - - protected void CopyToInputAndExpectations (NPath source) - { - source.Copy (InputDirectory); - source.Copy (ExpectationsDirectory); - } - - public NPath BeforeReferenceSourceDirectoryFor (string outputName) - { - return _directory.Combine ($"ref_source_before_{Path.GetFileNameWithoutExtension (outputName)}"); - } - - public NPath AfterReferenceSourceDirectoryFor (string outputName) - { - return _directory.Combine ($"ref_source_after_{Path.GetFileNameWithoutExtension (outputName)}"); - } - - public NPath BeforeReferenceResourceDirectoryFor (string outputName) - { - return _directory.Combine ($"ref_resource_before_{Path.GetFileNameWithoutExtension (outputName)}"); - } - - public NPath AfterReferenceResourceDirectoryFor (string outputName) - { - return _directory.Combine ($"ref_resource_after_{Path.GetFileNameWithoutExtension (outputName)}"); - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestLogWriter.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestLogWriter.cs deleted file mode 100644 index c8d4a40a7eabd..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestLogWriter.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using ILCompiler; -using ILCompiler.Logging; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestLogWriter : ILogWriter - { - private readonly StringWriter _infoStringWriter; - private readonly TextWriter _infoWriter; - - private readonly List _messageContainers; - - public TestLogWriter () - { - _infoStringWriter = new StringWriter (); - _infoWriter = TextWriter.Synchronized (_infoStringWriter); - _messageContainers = new List (); - } - - public TextWriter Writer => _infoWriter; - - public List GetLoggedMessages () - { - return _messageContainers; - } - - public void WriteError (MessageContainer error) - { - lock (_messageContainers) { - _messageContainers.Add (error); - } - } - - public void WriteMessage (MessageContainer message) - { - lock (_messageContainers) { - _messageContainers.Add (message); - } - } - - public void WriteWarning (MessageContainer warning) - { - lock (_messageContainers) { - _messageContainers.Add (warning); - } - } - } -} diff --git a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs b/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs deleted file mode 100644 index 3540250b709f3..0000000000000 --- a/src/coreclr/tools/aot/Mono.Linker.Tests/TestCasesRunner/TestRunner.cs +++ /dev/null @@ -1,165 +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.Linq; -using System.Threading.Tasks; -using Mono.Linker.Tests.TestCasesRunner; -using Mono.Cecil; -using Mono.Linker.Tests.Extensions; -using Mono.Linker.Tests.TestCases; -using Xunit.Sdk; - -namespace Mono.Linker.Tests.TestCasesRunner -{ - public class TestRunner - { - private readonly ObjectFactory _factory; - - public TestRunner (ObjectFactory factory) - { - _factory = factory; - } - - public virtual ILCompilerTestCaseResult? Run (TestCase testCase) - { - try { - using (var fullTestCaseAssemblyDefinition = AssemblyDefinition.ReadAssembly (testCase.OriginalTestCaseAssemblyPath.ToString ())) { - var compilationMetadataProvider = _factory.CreateCompilationMetadataProvider (testCase, fullTestCaseAssemblyDefinition); - - if (compilationMetadataProvider.IsIgnored (out string? ignoreReason)) - throw new IgnoreTestException (ignoreReason); - - var sandbox = Sandbox (testCase, compilationMetadataProvider); - var compilationResult = Compile (sandbox, compilationMetadataProvider); - using (var expectationsAssemblyDefinition = AssemblyDefinition.ReadAssembly (compilationResult.ExpectationsAssemblyPath.ToString ())) { - var metadataProvider = _factory.CreateMetadataProvider (testCase, expectationsAssemblyDefinition); - - sandbox.PopulateFromExpectations (metadataProvider); - - PrepForLink (sandbox, compilationResult); - return Link (testCase, sandbox, compilationResult, metadataProvider); - } - } - } catch (IgnoreTestException) { - return null; - } - } - - public virtual ILCompilerTestCaseResult Relink (ILCompilerTestCaseResult result) - { - PrepForLink (result.Sandbox, result.CompilationResult); - return Link (result.TestCase, result.Sandbox, result.CompilationResult, result.MetadataProvider); - } - - private TestCaseSandbox Sandbox (TestCase testCase, TestCaseCompilationMetadataProvider metadataProvider) - { - var sandbox = _factory.CreateSandbox (testCase); - sandbox.Populate (metadataProvider); - return sandbox; - } - - private ManagedCompilationResult Compile (TestCaseSandbox sandbox, TestCaseCompilationMetadataProvider metadataProvider) - { - var inputCompiler = _factory.CreateCompiler (sandbox, metadataProvider); - var expectationsCompiler = _factory.CreateCompiler (sandbox, metadataProvider); - var sourceFiles = sandbox.SourceFiles.Select (s => s.ToString ()).ToArray (); - - var assemblyName = metadataProvider.GetAssemblyName (); - - var commonReferences = metadataProvider.GetCommonReferencedAssemblies (sandbox.InputDirectory).ToArray (); - var mainAssemblyReferences = metadataProvider.GetReferencedAssemblies (sandbox.InputDirectory).ToArray (); - var resources = sandbox.ResourceFiles.ToArray (); - var additionalArguments = metadataProvider.GetSetupCompilerArguments ().ToArray (); - - var expectationsCommonReferences = metadataProvider.GetCommonReferencedAssemblies (sandbox.ExpectationsDirectory).ToArray (); - var expectationsMainAssemblyReferences = metadataProvider.GetReferencedAssemblies (sandbox.ExpectationsDirectory).ToArray (); - - var inputTask = Task.Run (() => inputCompiler.CompileTestIn (sandbox.InputDirectory, assemblyName!, sourceFiles, commonReferences, mainAssemblyReferences, null, resources, additionalArguments)); - var expectationsTask = Task.Run (() => expectationsCompiler.CompileTestIn (sandbox.ExpectationsDirectory, assemblyName!, sourceFiles, expectationsCommonReferences, expectationsMainAssemblyReferences, new[] { "INCLUDE_EXPECTATIONS" }, resources, additionalArguments)); - - NPath? inputAssemblyPath = null; - NPath? expectationsAssemblyPath = null; - try { - inputAssemblyPath = GetResultOfTaskThatMakesXUnitAssertions (inputTask); - expectationsAssemblyPath = GetResultOfTaskThatMakesXUnitAssertions (expectationsTask); - } catch (Exception) { - // If completing the input assembly task threw, we need to wait for the expectations task to complete before continuing - // otherwise we could set the next test up for a race condition with the expectations compilation over access to the sandbox directory - if (inputAssemblyPath == null && expectationsAssemblyPath == null) { - try { - expectationsTask.Wait (); - } catch (Exception) { - // Don't care, we want to throw the first exception - } - } - - throw; - } - - return new ManagedCompilationResult (inputAssemblyPath, expectationsAssemblyPath); - } - - protected virtual void PrepForLink (TestCaseSandbox sandbox, ManagedCompilationResult compilationResult) - { - } - - private ILCompilerTestCaseResult Link (TestCase testCase, TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, TestCaseMetadataProvider metadataProvider) - { - var trimmer = _factory.CreateTrimmer (); - - var builder = _factory.CreateTrimmerOptionsBuilder (metadataProvider); - - AddLinkOptions (sandbox, compilationResult, builder, metadataProvider); - - var logWriter = new TestLogWriter (); - trimmer.Trim (builder.Options, logWriter); - - return new ILCompilerTestCaseResult (testCase, compilationResult.InputAssemblyPath, compilationResult.ExpectationsAssemblyPath, sandbox, metadataProvider, compilationResult, logWriter); - } - - protected virtual void AddLinkOptions (TestCaseSandbox sandbox, ManagedCompilationResult compilationResult, ILCompilerOptionsBuilder builder, TestCaseMetadataProvider metadataProvider) - { - var caseDefinedOptions = metadataProvider.GetLinkerOptions (sandbox.InputDirectory); - - builder.AddOutputDirectory (sandbox.OutputDirectory.Combine (compilationResult.InputAssemblyPath.FileNameWithoutExtension + ".obj")); - - foreach (var rspFile in sandbox.ResponseFiles) - builder.AddResponseFile (rspFile); - - foreach (var inputReference in sandbox.InputDirectory.Files ()) { - var ext = inputReference.ExtensionWithDot; - if (ext == ".dll" || ext == ".exe") { - if (caseDefinedOptions.AssembliesAction.Contains (("link", inputReference.FileNameWithoutExtension))) { - builder.AddLinkAssembly (inputReference); - } else { - builder.AddReference (inputReference); - } - } - } - var coreAction = caseDefinedOptions.TrimMode ?? "skip"; - foreach (var extraReference in metadataProvider.GetExtraLinkerReferences ()) { - builder.AddReference (extraReference); - builder.AddAssemblyAction (coreAction, extraReference.FileNameWithoutExtension); - } - - builder.ProcessOptions (caseDefinedOptions); - - builder.ProcessTestInputAssembly (compilationResult.InputAssemblyPath); - } - - private T GetResultOfTaskThatMakesXUnitAssertions (Task task) - { - try { - return task.Result; - } catch (AggregateException e) { - if (e.InnerException != null) { - if (e.InnerException is XunitException) - throw e.InnerException; - } - - throw; - } - } - } -} diff --git a/src/coreclr/tools/aot/ilc.sln b/src/coreclr/tools/aot/ilc.sln index 2ea6f046a1b26..b1c7181908a26 100644 --- a/src/coreclr/tools/aot/ilc.sln +++ b/src/coreclr/tools/aot/ilc.sln @@ -22,13 +22,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Compiler.Tests", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.TypeSystem.Tests", "ILCompiler.TypeSystem.Tests\ILCompiler.TypeSystem.Tests.csproj", "{740CDFF4-B8EC-4A37-951B-C9FE9980EF2A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Linker.Tests", "Mono.Linker.Tests\Mono.Linker.Tests.csproj", "{4CF2ECD3-A1C3-4A28-AB08-A61C53114143}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Linker.Tests.Cases", "Mono.Linker.Tests.Cases\Mono.Linker.Tests.Cases.csproj", "{13F90593-7DF6-4B16-B6C1-283905C05A6A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Linker.Tests.Cases.Expectations", "Mono.Linker.Tests.Cases.Expectations\Mono.Linker.Tests.Cases.Expectations.csproj", "{26C08C03-921E-4795-AA0B-F3049416E300}" -EndProject Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ILLink.Shared\ILLink.Shared.projitems*{ff598e93-8e9e-4091-9f50-61a7572663ae}*SharedItemsImports = 13 + ILLink.Shared\ILLink.Shared.projitems*{ffbd9619-de6f-4a98-8732-8a14ec3c1a18}*SharedItemsImports = 5 + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Checked|Any CPU = Checked|Any CPU Checked|x64 = Checked|x64 @@ -182,60 +180,6 @@ Global {740CDFF4-B8EC-4A37-951B-C9FE9980EF2A}.Release|x64.Build.0 = Release|x64 {740CDFF4-B8EC-4A37-951B-C9FE9980EF2A}.Release|x86.ActiveCfg = Release|Any CPU {740CDFF4-B8EC-4A37-951B-C9FE9980EF2A}.Release|x86.Build.0 = Release|Any CPU - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Checked|Any CPU.ActiveCfg = Checked|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Checked|Any CPU.Build.0 = Checked|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Checked|x64.ActiveCfg = Checked|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Checked|x64.Build.0 = Checked|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Checked|x86.ActiveCfg = Checked|x86 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Checked|x86.Build.0 = Checked|x86 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Debug|Any CPU.ActiveCfg = Debug|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Debug|Any CPU.Build.0 = Debug|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Debug|x64.ActiveCfg = Debug|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Debug|x64.Build.0 = Debug|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Debug|x86.ActiveCfg = Debug|x86 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Debug|x86.Build.0 = Debug|x86 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Release|Any CPU.ActiveCfg = Release|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Release|Any CPU.Build.0 = Release|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Release|x64.ActiveCfg = Release|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Release|x64.Build.0 = Release|x64 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Release|x86.ActiveCfg = Release|x86 - {4CF2ECD3-A1C3-4A28-AB08-A61C53114143}.Release|x86.Build.0 = Release|x86 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Checked|Any CPU.ActiveCfg = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Checked|Any CPU.Build.0 = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Checked|x64.ActiveCfg = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Checked|x64.Build.0 = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Checked|x86.ActiveCfg = Debug|x86 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Checked|x86.Build.0 = Debug|x86 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Debug|Any CPU.ActiveCfg = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Debug|Any CPU.Build.0 = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Debug|x64.ActiveCfg = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Debug|x64.Build.0 = Debug|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Debug|x86.ActiveCfg = Debug|x86 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Debug|x86.Build.0 = Debug|x86 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Release|Any CPU.ActiveCfg = Release|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Release|Any CPU.Build.0 = Release|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Release|x64.ActiveCfg = Release|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Release|x64.Build.0 = Release|x64 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Release|x86.ActiveCfg = Release|x86 - {13F90593-7DF6-4B16-B6C1-283905C05A6A}.Release|x86.Build.0 = Release|x86 - {26C08C03-921E-4795-AA0B-F3049416E300}.Checked|Any CPU.ActiveCfg = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Checked|Any CPU.Build.0 = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Checked|x64.ActiveCfg = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Checked|x64.Build.0 = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Checked|x86.ActiveCfg = Debug|x86 - {26C08C03-921E-4795-AA0B-F3049416E300}.Checked|x86.Build.0 = Debug|x86 - {26C08C03-921E-4795-AA0B-F3049416E300}.Debug|Any CPU.ActiveCfg = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Debug|Any CPU.Build.0 = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Debug|x64.ActiveCfg = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Debug|x64.Build.0 = Debug|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Debug|x86.ActiveCfg = Debug|x86 - {26C08C03-921E-4795-AA0B-F3049416E300}.Debug|x86.Build.0 = Debug|x86 - {26C08C03-921E-4795-AA0B-F3049416E300}.Release|Any CPU.ActiveCfg = Release|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Release|Any CPU.Build.0 = Release|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Release|x64.ActiveCfg = Release|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Release|x64.Build.0 = Release|x64 - {26C08C03-921E-4795-AA0B-F3049416E300}.Release|x86.ActiveCfg = Release|x86 - {26C08C03-921E-4795-AA0B-F3049416E300}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -243,8 +187,4 @@ Global GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A484CF9D-B203-427F-9D15-A5BBC6013421} EndGlobalSection - GlobalSection(SharedMSBuildProjectFiles) = preSolution - ILLink.Shared\ILLink.Shared.projitems*{ff598e93-8e9e-4091-9f50-61a7572663ae}*SharedItemsImports = 13 - ILLink.Shared\ILLink.Shared.projitems*{ffbd9619-de6f-4a98-8732-8a14ec3c1a18}*SharedItemsImports = 5 - EndGlobalSection EndGlobal diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index bad094900a090..d182b8fee80ee 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -17,7 +17,6 @@ struct JitInterfaceCallbacks void (* getMethodSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO* sig, CORINFO_CLASS_HANDLE memberParent); bool (* getMethodInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info); CorInfoInline (* canInline)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd); - void (* beginInlining)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd); void (* reportInliningDecision)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char* reason); bool (* canTailCall)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE declaredCalleeHnd, CORINFO_METHOD_HANDLE exactCalleeHnd, bool fIsTailPrefix); void (* reportTailCallDecision)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char* reason); @@ -256,15 +255,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual void beginInlining( - CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) -{ - CorInfoExceptionClass* pException = nullptr; - _callbacks->beginInlining(_thisHandle, &pException, inlinerHnd, inlineeHnd); - if (pException != nullptr) throw pException; -} - virtual void reportInliningDecision( CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, diff --git a/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs b/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs index e99fc610d86ca..a498bfd9e21d5 100644 --- a/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs +++ b/src/coreclr/tools/dotnet-pgo/MibcEmitter.cs @@ -215,8 +215,6 @@ private static void AddAssembliesAssociatedWithMethod(MethodDesc method, HashSet public static int GenerateMibcFile(TypeSystemContext tsc, FileInfo outputFileName, IEnumerable methodsToAttemptToPlaceIntoProfileData, bool validate, bool uncompressed) { TypeSystemMetadataEmitter emitter = new TypeSystemMetadataEmitter(new AssemblyName(outputFileName.Name), tsc); - emitter.InjectSystemPrivateCanon(); - emitter.AllowUseOfAddGlobalMethod(); SortedDictionary groups = new SortedDictionary(); StringBuilder mibcGroupNameBuilder = new StringBuilder(); diff --git a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs index 31a5caee14c23..bb32521c0b750 100644 --- a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs +++ b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemContext.cs @@ -153,8 +153,8 @@ public TypeRefTypeSystemContext(IEnumerable refReaders) } else { - var fieldType = ecmaSigParse.ParseFieldSignature(out var embeddedSigData); - ownerType.GetOrAddField(name, fieldType, embeddedSigData); + var fieldType = ecmaSigParse.ParseFieldSignature(); + ownerType.GetOrAddField(name, fieldType); } } diff --git a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemField.cs b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemField.cs index a380db86080bc..5f261b4932c3f 100644 --- a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemField.cs +++ b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemField.cs @@ -15,14 +15,12 @@ class TypeRefTypeSystemField : FieldDesc TypeRefTypeSystemType _type; string _name; TypeDesc _fieldType; - EmbeddedSignatureData[] _embeddedSignatureData; - public TypeRefTypeSystemField(TypeRefTypeSystemType type, string name, TypeDesc fieldType, EmbeddedSignatureData[] embeddedSigData) + public TypeRefTypeSystemField(TypeRefTypeSystemType type, string name, TypeDesc fieldType) { _type = type; _name = name; _fieldType = fieldType; - _embeddedSignatureData = embeddedSigData; } public override string Name => _name; @@ -30,8 +28,6 @@ public TypeRefTypeSystemField(TypeRefTypeSystemType type, string name, TypeDesc public override TypeDesc FieldType => _fieldType; - public override EmbeddedSignatureData[] GetEmbeddedSignatureData() => _embeddedSignatureData; - public override bool IsStatic => throw new NotImplementedException(); public override bool IsInitOnly => throw new NotImplementedException(); diff --git a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs index af3bb5ae72c24..6b5689805e93c 100644 --- a/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs +++ b/src/coreclr/tools/dotnet-pgo/TypeRefTypeSystem/TypeRefTypeSystemType.cs @@ -119,12 +119,12 @@ public MethodDesc GetOrAddMethod(string name, MethodSignature signature) return method; } - public FieldDesc GetOrAddField(string name, TypeDesc fieldType, EmbeddedSignatureData[] embeddedSigData) + public FieldDesc GetOrAddField(string name, TypeDesc fieldType) { FieldDesc fld = GetField(name); if (fld == null) { - TypeRefTypeSystemField newField = new TypeRefTypeSystemField(this, name, fieldType, embeddedSigData); + TypeRefTypeSystemField newField = new TypeRefTypeSystemField(this, name, fieldType); fld = newField; _fields.Add(newField); } diff --git a/src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp b/src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp index 2ff9b3cbe3690..1cfbc598dbee1 100644 --- a/src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbdumpmap.cpp @@ -93,9 +93,8 @@ void DumpMap(int index, MethodContext* mc) bool hasClassProfile = false; bool hasMethodProfile = false; bool hasLikelyClass = false; - bool hasLikelyMethod = false; ICorJitInfo::PgoSource pgoSource = ICorJitInfo::PgoSource::Unknown; - if (mc->hasPgoData(hasEdgeProfile, hasClassProfile, hasMethodProfile, hasLikelyClass, hasLikelyMethod, pgoSource)) + if (mc->hasPgoData(hasEdgeProfile, hasClassProfile, hasMethodProfile, hasLikelyClass, pgoSource)) { rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_PGO); @@ -119,11 +118,6 @@ void DumpMap(int index, MethodContext* mc) rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_LIKELY_CLASS); } - if (hasLikelyMethod) - { - rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_LIKELY_METHOD); - } - if (pgoSource == ICorJitInfo::PgoSource::Static) { rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_STATIC_PROFILE); diff --git a/src/coreclr/tools/superpmi/mcs/verbjitflags.cpp b/src/coreclr/tools/superpmi/mcs/verbjitflags.cpp index 33190d3fbd996..a3e31a1f73062 100644 --- a/src/coreclr/tools/superpmi/mcs/verbjitflags.cpp +++ b/src/coreclr/tools/superpmi/mcs/verbjitflags.cpp @@ -31,9 +31,8 @@ int verbJitFlags::DoWork(const char* nameOfInput) bool hasClassProfile = false; bool hasMethodProfile = false; bool hasLikelyClass = false; - bool hasLikelyMethod = false; ICorJitInfo::PgoSource pgoSource = ICorJitInfo::PgoSource::Unknown; - if (mc->hasPgoData(hasEdgeProfile, hasClassProfile, hasMethodProfile, hasLikelyClass, hasLikelyMethod, pgoSource)) + if (mc->hasPgoData(hasEdgeProfile, hasClassProfile, hasMethodProfile, hasLikelyClass, pgoSource)) { rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_PGO); @@ -57,11 +56,6 @@ int verbJitFlags::DoWork(const char* nameOfInput) rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_LIKELY_CLASS); } - if (hasLikelyMethod) - { - rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_LIKELY_METHOD); - } - if (pgoSource == ICorJitInfo::PgoSource::Static) { rawFlags |= 1ULL << (EXTRA_JIT_FLAGS::HAS_STATIC_PROFILE); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index df50466b476d3..97be9fbfc9fca 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -5607,10 +5607,9 @@ void MethodContext::dmpGetPgoInstrumentationResults(DWORDLONG key, const Agnosti } break; case ICorJitInfo::PgoInstrumentationKind::GetLikelyClass: - case ICorJitInfo::PgoInstrumentationKind::GetLikelyMethod: { - // (N)umber, (L)ikelihood, (H)andle - printf("N %u L %u H %016llX", (unsigned)(pBuf[i].Other >> 8), (unsigned)(pBuf[i].Other && 0xFF), CastHandle(*(uintptr_t*)(pInstrumentationData + pBuf[i].Offset))); + // (N)umber, (L)ikelihood, (C)lass + printf("N %u L %u C %016llX", (unsigned)(pBuf[i].Other >> 8), (unsigned)(pBuf[i].Other && 0xFF), CastHandle(*(uintptr_t*)(pInstrumentationData + pBuf[i].Offset))); } break; default: @@ -7073,13 +7072,12 @@ int MethodContext::dumpMD5HashToBuffer(BYTE* pBuffer, int bufLen, char* hash, in return m_hash.HashBuffer(pBuffer, bufLen, hash, hashLen); } -bool MethodContext::hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool& hasMethodProfile, bool& hasLikelyClass, bool& hasLikelyMethod, ICorJitInfo::PgoSource& pgoSource) +bool MethodContext::hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool& hasMethodProfile, bool& hasLikelyClass, ICorJitInfo::PgoSource& pgoSource) { hasEdgeProfile = false; hasClassProfile = false; hasMethodProfile = false; hasLikelyClass = false; - hasLikelyMethod = false; // Obtain the Method Info structure for this method CORINFO_METHOD_INFO info; @@ -7104,9 +7102,8 @@ bool MethodContext::hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool hasClassProfile |= (schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes); hasMethodProfile |= (schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::HandleHistogramMethods); hasLikelyClass |= (schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::GetLikelyClass); - hasLikelyMethod |= (schema[i].InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::GetLikelyMethod); - if (hasEdgeProfile && hasClassProfile && hasLikelyClass && hasLikelyMethod) + if (hasEdgeProfile && hasClassProfile && hasLikelyClass) { break; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 5009d6b6a69c4..816682b1effe9 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -54,7 +54,6 @@ enum EXTRA_JIT_FLAGS HAS_STATIC_PROFILE = 59, HAS_DYNAMIC_PROFILE = 58, HAS_METHOD_PROFILE = 57, - HAS_LIKELY_METHOD = 56, }; // Asserts to catch changes in corjit flags definitions. @@ -65,8 +64,6 @@ static_assert((int)EXTRA_JIT_FLAGS::HAS_CLASS_PROFILE == (int)CORJIT_FLAGS::CorJ static_assert((int)EXTRA_JIT_FLAGS::HAS_LIKELY_CLASS == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED33, "Jit Flags Mismatch"); static_assert((int)EXTRA_JIT_FLAGS::HAS_STATIC_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED32, "Jit Flags Mismatch"); static_assert((int)EXTRA_JIT_FLAGS::HAS_DYNAMIC_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED31, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_METHOD_PROFILE == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED30, "Jit Flags Mismatch"); -static_assert((int)EXTRA_JIT_FLAGS::HAS_LIKELY_METHOD == (int)CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_UNUSED29, "Jit Flags Mismatch"); class MethodContext { @@ -109,7 +106,7 @@ class MethodContext int dumpMethodIdentityInfoToBuffer(char* buff, int len, bool ignoreMethodName = false, CORINFO_METHOD_INFO* optInfo = nullptr, unsigned optFlags = 0); int dumpMethodMD5HashToBuffer(char* buff, int len, bool ignoreMethodName = false, CORINFO_METHOD_INFO* optInfo = nullptr, unsigned optFlags = 0); - bool hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool& hasMethodProfile, bool& hasLikelyClass, bool& hasLikelyMethod, ICorJitInfo::PgoSource& pgoSource); + bool hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool& hasMethodProfile, bool& hasLikelyClass, ICorJitInfo::PgoSource& pgoSource); void recGlobalContext(const MethodContext& other); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp index b51a54ba18385..1d1d4d53b1a84 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp @@ -285,7 +285,6 @@ std::string SpmiDumpHelper::DumpJitFlags(unsigned long long flags) AddFlagNumeric(HAS_CLASS_PROFILE, EXTRA_JIT_FLAGS::HAS_CLASS_PROFILE); AddFlagNumeric(HAS_METHOD_PROFILE, EXTRA_JIT_FLAGS::HAS_METHOD_PROFILE); AddFlagNumeric(HAS_LIKELY_CLASS, EXTRA_JIT_FLAGS::HAS_LIKELY_CLASS); - AddFlagNumeric(HAS_LIKELY_METHOD, EXTRA_JIT_FLAGS::HAS_LIKELY_METHOD); AddFlagNumeric(HAS_STATIC_PROFILE, EXTRA_JIT_FLAGS::HAS_STATIC_PROFILE); AddFlagNumeric(HAS_DYNAMIC_PROFILE, EXTRA_JIT_FLAGS::HAS_DYNAMIC_PROFILE); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index b939f4cb844fb..4ce8db665615b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -115,13 +115,6 @@ CorInfoInline interceptor_ICJI::canInline(CORINFO_METHOD_HANDLE callerHnd, /* return temp; } -void interceptor_ICJI::beginInlining(CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) -{ - mc->cr->AddCall("beginInlining"); - original_ICorJitInfo->beginInlining(inlinerHnd, inlineeHnd); -} - // Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all // inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the // JIT. diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index af768ca0933b1..79e3536ba524c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -59,14 +59,6 @@ CorInfoInline interceptor_ICJI::canInline( return original_ICorJitInfo->canInline(callerHnd, calleeHnd); } -void interceptor_ICJI::beginInlining( - CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) -{ - mcs->AddCall("beginInlining"); - original_ICorJitInfo->beginInlining(inlinerHnd, inlineeHnd); -} - void interceptor_ICJI::reportInliningDecision( CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 957cadd8c57c3..7d4feacc10d6e 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -53,13 +53,6 @@ CorInfoInline interceptor_ICJI::canInline( return original_ICorJitInfo->canInline(callerHnd, calleeHnd); } -void interceptor_ICJI::beginInlining( - CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) -{ - original_ICorJitInfo->beginInlining(inlinerHnd, inlineeHnd); -} - void interceptor_ICJI::reportInliningDecision( CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index bb6592bb8b39b..7f2203edd7ac1 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -100,11 +100,6 @@ CorInfoInline MyICJI::canInline(CORINFO_METHOD_HANDLE callerHnd, /* IN */ return result; } -void MyICJI::beginInlining(CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd) -{ - // do nothing -} // Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all // inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the // JIT. diff --git a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp index c43ed6fad684d..5ed5f155c2d23 100644 --- a/src/coreclr/tools/superpmi/superpmi/superpmi.cpp +++ b/src/coreclr/tools/superpmi/superpmi/superpmi.cpp @@ -371,8 +371,7 @@ int __cdecl main(int argc, char* argv[]) st3.Start(); res = jit->CompileMethod(mc, reader->GetMethodContextIndex(), collectThroughput, &baseMetrics); st3.Stop(); - LogDebug("Method %d compiled%s in %fms, result %d", - reader->GetMethodContextIndex(), (o.nameOfJit2 == nullptr) ? "" : " by JIT1", st3.GetMilliseconds(), res); + LogDebug("Method %d compiled in %fms, result %d", reader->GetMethodContextIndex(), st3.GetMilliseconds(), res); totalBaseMetrics.AggregateFrom(baseMetrics); @@ -407,8 +406,8 @@ int __cdecl main(int argc, char* argv[]) if (res2 == JitInstance::RESULT_ERROR) { errorCount2++; - LogError("Method %d of size %d failed to load and compile correctly by JIT2 (%s).", - reader->GetMethodContextIndex(), mc->methodSize, o.nameOfJit2); + LogError("Method %d of size %d failed to load and compile correctly by JIT2.", + reader->GetMethodContextIndex(), mc->methodSize); if (errorCount2 == o.failureLimit) { LogError("More than %d methods compilation failed by JIT2. Skip compiling remaining methods.", o.failureLimit); @@ -566,13 +565,11 @@ int __cdecl main(int argc, char* argv[]) if (res == JitInstance::RESULT_ERROR) { errorCount++; - LogError("Method %d of size %d failed to load and compile correctly%s (%s).", - reader->GetMethodContextIndex(), mc->methodSize, - (o.nameOfJit2 == nullptr) ? "" : " by JIT1", o.nameOfJit); + LogError("main method %d of size %d failed to load and compile correctly.", + reader->GetMethodContextIndex(), mc->methodSize); if (errorCount == o.failureLimit) { - LogError("More than %d methods failed%s. Skip compiling remaining methods.", - o.failureLimit, (o.nameOfJit2 == nullptr) ? "" : " by JIT1"); + LogError("More than %d methods failed. Skip compiling remaining methods.", o.failureLimit); break; } if ((o.reproName != nullptr) && (o.indexCount == -1)) diff --git a/src/coreclr/unwinder/ppc64le/unwinder_ppc64le.cpp b/src/coreclr/unwinder/ppc64le/unwinder_ppc64le.cpp deleted file mode 100644 index 66cb24b46e6e7..0000000000000 --- a/src/coreclr/unwinder/ppc64le/unwinder_ppc64le.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// - -#include "stdafx.h" -#include "utilcode.h" -#include "crosscomp.h" - -#error Unsupported platform - diff --git a/src/coreclr/utilcode/CMakeLists.txt b/src/coreclr/utilcode/CMakeLists.txt index 76d5b0e61dc0f..c55965b239600 100644 --- a/src/coreclr/utilcode/CMakeLists.txt +++ b/src/coreclr/utilcode/CMakeLists.txt @@ -27,6 +27,7 @@ set(UTILCODE_COMMON_SOURCES comex.cpp guidfromname.cpp memorypool.cpp + iallocator.cpp loaderheap.cpp outstring.cpp ilformatter.cpp diff --git a/src/coreclr/utilcode/clrconfig.cpp b/src/coreclr/utilcode/clrconfig.cpp index 5df6748739ccb..caad3b594a6ea 100644 --- a/src/coreclr/utilcode/clrconfig.cpp +++ b/src/coreclr/utilcode/clrconfig.cpp @@ -200,11 +200,15 @@ namespace #if defined(DEBUG) && !defined(SELF_NO_HOST) // Validate the cache and no-cache logic result in the same answer SString nameToConvert(name); + SString nameAsUTF8; + nameToConvert.ConvertToUTF8(nameAsUTF8); + SString valueAsUTF8; + temp.ConvertToUTF8(valueAsUTF8); - CLRConfigNoCache nonCache = CLRConfigNoCache::Get(nameToConvert.GetUTF8(), noPrefix); + CLRConfigNoCache nonCache = CLRConfigNoCache::Get(nameAsUTF8.GetUTF8NoConvert(), noPrefix); LPCSTR valueNoCache = nonCache.AsString(); - _ASSERTE(SString::_stricmp(valueNoCache, temp.GetUTF8()) == 0); + _ASSERTE(SString::_stricmp(valueNoCache, valueAsUTF8.GetUTF8NoConvert()) == 0); #endif // defined(DEBUG) && !defined(SELF_NO_HOST) } } @@ -630,8 +634,8 @@ void CLRConfig::Initialize() if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DisableConfigCache) != 0) return; - const WCHAR prefixC = (WCHAR)towlower(COMPLUS_PREFIX[0]); - const WCHAR prefixD = (WCHAR)towlower(DOTNET_PREFIX[0]); + const WCHAR prefixC = towlower(COMPLUS_PREFIX[0]); + const WCHAR prefixD = towlower(DOTNET_PREFIX[0]); // Create a cache of environment variables WCHAR* wszStrings = GetEnvironmentStringsW(); @@ -641,7 +645,7 @@ void CLRConfig::Initialize() // null terminated strings for(WCHAR *wszCurr = wszStrings; *wszCurr; wszCurr++) { - WCHAR wch = (WCHAR)towlower(*wszCurr); + WCHAR wch = towlower(*wszCurr); // Lets only cache env variables with targeted prefixes bool matchC = wch == prefixC; diff --git a/src/coreclr/utilcode/debug.cpp b/src/coreclr/utilcode/debug.cpp index e78de404115e5..3f4c74d420f9d 100644 --- a/src/coreclr/utilcode/debug.cpp +++ b/src/coreclr/utilcode/debug.cpp @@ -364,7 +364,7 @@ bool _DbgBreakCheck( " Image: %s\n\n", GetCurrentProcessId(), GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentThreadId(), - szExpr, szFile, iLine, modulePath.GetUTF8()); + szExpr, szFile, iLine, modulePath.GetUTF8NoConvert()); formattedMessages = TRUE; } @@ -680,11 +680,11 @@ void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, cons " File: %s, Line: %d Image:\n%s\n", GetCurrentProcessId(), GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentThreadId(), - szExpr, szFile, iLine, modulePath.GetUTF8()); - OutputDebugStringUtf8(buffer.GetUTF8()); + szExpr, szFile, iLine, modulePath.GetUTF8NoConvert()); + OutputDebugStringUtf8(buffer.GetUTF8NoConvert()); // Write out the error to the console - printf(buffer.GetUTF8()); + printf(buffer.GetUTF8NoConvert()); // Log to the stress log. Note that we can't include the szExpr b/c that // may not be a string literal (particularly for formatt-able asserts). diff --git a/src/coreclr/utilcode/executableallocator.cpp b/src/coreclr/utilcode/executableallocator.cpp index 9536b673f53a5..8a1614e080f6a 100644 --- a/src/coreclr/utilcode/executableallocator.cpp +++ b/src/coreclr/utilcode/executableallocator.cpp @@ -249,8 +249,7 @@ bool ExecutableAllocator::Initialize() { if (!VMToOSInterface::CreateDoubleMemoryMapper(&m_doubleMemoryMapperHandle, &m_maxExecutableCodeSize)) { - g_isWXorXEnabled = false; - return true; + return false; } m_CriticalSection = ClrCreateCriticalSection(CrstExecutableAllocatorLock,CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD)); diff --git a/src/coreclr/utilcode/iallocator.cpp b/src/coreclr/utilcode/iallocator.cpp new file mode 100644 index 0000000000000..9e1ea5ed90662 --- /dev/null +++ b/src/coreclr/utilcode/iallocator.cpp @@ -0,0 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "stdafx.h" // Precompiled header key. +#include "iallocator.h" +#include "defaultallocator.h" + +// static +DefaultAllocator DefaultAllocator::s_singleton; diff --git a/src/coreclr/utilcode/prettyprintsig.cpp b/src/coreclr/utilcode/prettyprintsig.cpp index f6b187099f0aa..ac6d7db6847dc 100644 --- a/src/coreclr/utilcode/prettyprintsig.cpp +++ b/src/coreclr/utilcode/prettyprintsig.cpp @@ -788,12 +788,8 @@ static HRESULT PrettyPrintTypeA( break; case ELEMENT_TYPE_FNPTR: - { - IfFailGo(appendStrA(out, "fnptr ")); - CQuickBytes qbOut; - IfFailGo(PrettyPrintSigWorkerInternal(typePtr, (typeEnd - typePtr), "", &qbOut,pIMDI)); - IfFailGo(appendStrA(out, (char *)qbOut.Ptr())); - } + IfFailGo(appendStrA(out, "fnptr ")); + IfFailGo(PrettyPrintSigWorkerInternal(typePtr, (typeEnd - typePtr), "", out,pIMDI)); break; case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: diff --git a/src/coreclr/utilcode/sstring.cpp b/src/coreclr/utilcode/sstring.cpp index 75e90977775af..ec3c340ff23d3 100644 --- a/src/coreclr/utilcode/sstring.cpp +++ b/src/coreclr/utilcode/sstring.cpp @@ -469,29 +469,6 @@ void SString::SetANSI(const ANSI *string, COUNT_T count) SS_RETURN; } -//----------------------------------------------------------------------------- -// Set this string to a copy of the given UTF16 string transcoded to UTF8 -//----------------------------------------------------------------------------- -void SString::SetAndConvertToUTF8(const WCHAR *string) -{ - SS_CONTRACT_VOID - { - // !!! Check for illegal UTF8 encoding? - INSTANCE_CHECK; - PRECONDITION(CheckPointer(string, NULL_OK)); - THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - SS_CONTRACT_END; - - SString utf16Str(Literal, string); - - utf16Str.ConvertToUTF8(*this); - - SS_RETURN; -} - //----------------------------------------------------------------------------- // Set this string to the given unicode character //----------------------------------------------------------------------------- @@ -800,39 +777,6 @@ void SString::ConvertToUnicode(const CIterator &i) const RETURN; } -//----------------------------------------------------------------------------- -// Convert the internal representation for this String to UTF8. -//----------------------------------------------------------------------------- -void SString::ConvertToUTF8() const -{ - CONTRACT_VOID - { - POSTCONDITION(IsRepresentation(REPRESENTATION_UTF8)); - if (IsRepresentation(REPRESENTATION_UTF8)) NOTHROW; else THROWS; - GC_NOTRIGGER; - SUPPORTS_DAC_HOST_ONLY; - } - CONTRACT_END; - - if (!IsRepresentation(REPRESENTATION_UTF8)) - { - if (IsRepresentation(REPRESENTATION_ASCII)) - { - // ASCII is a subset of UTF8, so we can just set the representation. - (const_cast(this))->SetRepresentation(REPRESENTATION_UTF8); - } - else - { - StackSString s; - ConvertToUTF8(s); - PREFIX_ASSUME(!s.IsImmutable()); - (const_cast(this))->Set(s); - } - } - - RETURN; -} - //----------------------------------------------------------------------------- // Set s to be a copy of this string's contents, but in the unicode format. //----------------------------------------------------------------------------- @@ -1843,6 +1787,66 @@ const CHAR *SString::GetANSI(AbstractScratchBuffer &scratch) const SS_RETURN ((SString&)scratch).GetRawANSI(); } +//----------------------------------------------------------------------------- +// Get a const pointer to the internal buffer as a UTF8 string. +//----------------------------------------------------------------------------- +const UTF8 *SString::GetUTF8(AbstractScratchBuffer &scratch) const +{ + CONTRACT(const UTF8 *) + { + INSTANCE_CHECK_NULL; + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + if (IsRepresentation(REPRESENTATION_UTF8)) + RETURN GetRawUTF8(); + + ConvertToUTF8((SString&)scratch); + RETURN ((SString&)scratch).GetRawUTF8(); +} + +const UTF8 *SString::GetUTF8(AbstractScratchBuffer &scratch, COUNT_T *pcbUtf8) const +{ + CONTRACT(const UTF8 *) + { + INSTANCE_CHECK_NULL; + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + if (IsRepresentation(REPRESENTATION_UTF8)) + { + *pcbUtf8 = GetRawCount() + 1; + RETURN GetRawUTF8(); + } + + *pcbUtf8 = ConvertToUTF8((SString&)scratch); + RETURN ((SString&)scratch).GetRawUTF8(); +} + +//----------------------------------------------------------------------------- +// Get a const pointer to the internal buffer which must already be a UTF8 string. +// This avoids the need to create a scratch buffer we know will never be used. +//----------------------------------------------------------------------------- +const UTF8 *SString::GetUTF8NoConvert() const +{ + CONTRACT(const UTF8 *) + { + INSTANCE_CHECK_NULL; + THROWS; + GC_NOTRIGGER; + } + CONTRACT_END; + + if (IsRepresentation(REPRESENTATION_UTF8)) + RETURN GetRawUTF8(); + + ThrowHR(E_INVALIDARG); +} + //----------------------------------------------------------------------------- // Safe version of sprintf. // Prints formatted ansi text w/ var args to this buffer. diff --git a/src/coreclr/utilcode/util.cpp b/src/coreclr/utilcode/util.cpp index b4fec28360d24..58423a704e970 100644 --- a/src/coreclr/utilcode/util.cpp +++ b/src/coreclr/utilcode/util.cpp @@ -23,13 +23,6 @@ #ifndef DACCESS_COMPILE UINT32 g_nClrInstanceId = 0; - -#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64) -// Flag to check if atomics feature is available on -// the machine -bool g_arm64_atomics_present = false; -#endif - #endif //!DACCESS_COMPILE //***************************************************************************** @@ -2600,6 +2593,161 @@ void PutArm64Rel12(UINT32 * pCode, INT32 imm12) _ASSERTE(GetArm64Rel12(pCode) == imm12); } +//--------------------------------------------------------------------- +// Splits a command line into argc/argv lists, using the VC7 parsing rules. +// +// This functions interface mimics the CommandLineToArgvW api. +// +// If function fails, returns NULL. +// +// If function suceeds, call delete [] on return pointer when done. +// +//--------------------------------------------------------------------- +// NOTE: Implementation-wise, once every few years it would be a good idea to +// compare this code with the C runtime library's parse_cmdline method, +// which is in vctools\crt\crtw32\startup\stdargv.c. (Note we don't +// support wild cards, and we use Unicode characters exclusively.) +// We are up to date as of ~6/2005. +//--------------------------------------------------------------------- +LPWSTR *SegmentCommandLine(LPCWSTR lpCmdLine, DWORD *pNumArgs) +{ + STATIC_CONTRACT_NOTHROW; + STATIC_CONTRACT_GC_NOTRIGGER; + STATIC_CONTRACT_FAULT; + + + *pNumArgs = 0; + + int nch = (int)wcslen(lpCmdLine); + + // Calculate the worstcase storage requirement. (One pointer for + // each argument, plus storage for the arguments themselves.) + int cbAlloc = (nch+1)*sizeof(LPWSTR) + sizeof(WCHAR)*(nch + 1); + LPWSTR pAlloc = new (nothrow) WCHAR[cbAlloc / sizeof(WCHAR)]; + if (!pAlloc) + return NULL; + + LPWSTR *argv = (LPWSTR*) pAlloc; // We store the argv pointers in the first halt + LPWSTR pdst = (LPWSTR)( ((BYTE*)pAlloc) + sizeof(LPWSTR)*(nch+1) ); // A running pointer to second half to store arguments + LPCWSTR psrc = lpCmdLine; + WCHAR c; + BOOL inquote; + BOOL copychar; + int numslash; + + // First, parse the program name (argv[0]). Argv[0] is parsed under + // special rules. Anything up to the first whitespace outside a quoted + // subtring is accepted. Backslashes are treated as normal characters. + argv[ (*pNumArgs)++ ] = pdst; + inquote = FALSE; + do { + if (*psrc == W('"') ) + { + inquote = !inquote; + c = *psrc++; + continue; + } + *pdst++ = *psrc; + + c = *psrc++; + + } while ( (c != W('\0') && (inquote || (c != W(' ') && c != W('\t')))) ); + + if ( c == W('\0') ) { + psrc--; + } else { + *(pdst-1) = W('\0'); + } + + inquote = FALSE; + + + + /* loop on each argument */ + for(;;) + { + if ( *psrc ) + { + while (*psrc == W(' ') || *psrc == W('\t')) + { + ++psrc; + } + } + + if (*psrc == W('\0')) + break; /* end of args */ + + /* scan an argument */ + argv[ (*pNumArgs)++ ] = pdst; + + /* loop through scanning one argument */ + for (;;) + { + copychar = 1; + /* Rules: 2N backslashes + " ==> N backslashes and begin/end quote + 2N+1 backslashes + " ==> N backslashes + literal " + N backslashes ==> N backslashes */ + numslash = 0; + while (*psrc == W('\\')) + { + /* count number of backslashes for use below */ + ++psrc; + ++numslash; + } + if (*psrc == W('"')) + { + /* if 2N backslashes before, start/end quote, otherwise + copy literally */ + if (numslash % 2 == 0) + { + if (inquote && psrc[1] == W('"')) + { + psrc++; /* Double quote inside quoted string */ + } + else + { + /* skip first quote char and copy second */ + copychar = 0; /* don't copy quote */ + inquote = !inquote; + } + } + numslash /= 2; /* divide numslash by two */ + } + + /* copy slashes */ + while (numslash--) + { + *pdst++ = W('\\'); + } + + /* if at end of arg, break loop */ + if (*psrc == W('\0') || (!inquote && (*psrc == W(' ') || *psrc == W('\t')))) + break; + + /* copy character into argument */ + if (copychar) + { + *pdst++ = *psrc; + } + ++psrc; + } + + /* null-terminate the argument */ + + *pdst++ = W('\0'); /* terminate string */ + } + + /* We put one last argument in -- a null ptr */ + argv[ (*pNumArgs) ] = NULL; + + // If we hit this assert, we overwrote our destination buffer. + // Since we're supposed to allocate for the worst + // case, either the parsing rules have changed or our worse case + // formula is wrong. + _ASSERTE((BYTE*)pdst <= (BYTE*)pAlloc + cbAlloc); + return argv; +} + //====================================================================== // This function returns true, if it can determine that the instruction pointer // refers to a code address that belongs in the range of the given image. diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 6983f21238b23..8c0b03342d016 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -364,6 +364,7 @@ set(VM_SOURCES_WKS runtimehandles.cpp safehandle.cpp simplerwlock.cpp + sourceline.cpp stackingallocator.cpp stringliteralmap.cpp stubcache.cpp @@ -464,6 +465,7 @@ set(VM_HEADERS_WKS reflectioninvocation.h runtimehandles.h simplerwlock.hpp + sourceline.h stackingallocator.h stringliteralmap.h stubcache.h diff --git a/src/coreclr/vm/ClrEtwAll.man b/src/coreclr/vm/ClrEtwAll.man index 761d650be7e51..a55dec687c962 100644 --- a/src/coreclr/vm/ClrEtwAll.man +++ b/src/coreclr/vm/ClrEtwAll.man @@ -446,13 +446,7 @@ - - - - - + @@ -1585,24 +1579,6 @@ - -